【问题标题】:Python - shallow copy is not enough. Deepcopy or any alternative to improve speed?Python - 浅拷贝是不够的。 Deepcopy 或任何提高速度的替代方法?
【发布时间】:2015-07-01 09:15:32
【问题描述】:

我有这个“模板”字典:

_premium_per_month = {1: [0.0, []], 2: [0.0, []], 2: [0.0, []], 3: [0.0, []], 4: [0.0, []], 5: [0.0, []], 
        6: [0.0, []], 7: [0.0, []], 8: [0.0, []],
        9: [0.0, []], 10: [0.0, []], 11: [0.0, []], 12: [0.0, []]}

有一种方法可以使用此字典并构建添加值。但是,当浅拷贝字典中的值发生变化时,模板字典中的值也会发生变化。那么我应该使用 deepcopy 还是有一些提示/技巧来获得更好/更快的副本或模式(也许我的模式是错误的)?

为了更好地理解它的作用,看看这个方法(它被简化了,只是为了展示核心问题)

def test(_premium_per_month):
  #premium_per_month = copy.deepcopy(_premium_per_month) this one works
  premium_per_month = _premium_per_month.copy() #not work
  for i in range(3):
      if i > 0:
        premium_per_month[i][0] += 20
  return premium_per_month

所以使用简单的复制,当然会改变原来的字典。 deepcopy 是解决此问题的正确方法还是我应该更改其他内容?

【问题讨论】:

  • 你为什么要抄袭?
  • 因为您的字典中的值是列表形式的,所以您别无选择,只能使用deepcopy。使用浅拷贝,新字典将只包含对现有列表的引用。
  • 是的,我是这么认为的。感谢您的意见。
  • @Andrius,你还没说你为什么要抄袭
  • @PadraicCunningham 我需要那个原始字典作为基础。然后使用它在列表中插入最初具有空值的值,例如[0.0, []]。第一个在迭代另一个对象时使用递增浮点数,然后将该对象 id 附加到第二项,即列表中。然后在其他地方使用这样的字典。再次调用方法时,该模板应该为空,这就是我要复制它的原因。如果没有,它将具有以前的值,并且会搞砸一切。还有一个想法是在方法中构建字典而不使用任何模板字典。不知道哪种方法更好。

标签: python dictionary deep-copy shallow-copy


【解决方案1】:

我想如果我把那个模板方法全部放弃的话这个会更有效(注意。在这里显示我在 cmets 中提到的对象,所以它会显示为什么我使用值作为列表,它被称为 contracts_list_premium_per_month这里根本不用)?

from datetime import datetime

def test(self, contracts_list):
    premium_per_month = {}
    for contract in contracts_list:
        dt = datetime.strptime(contract.date_start, self._date_fmt)
        if d.get(dt.month):
            premium_per_month[dt.month][0] += contract.premium
            premium_per_month[dt.month][1].append(contract.id)
        else:
            val_lst = [contract.premium, [contract.id]]
            premium_per_month[dt.month] = val_lst 
    return premium_per_month

【讨论】:

  • 是的,你应该每次都构建一个 new 字典(或者如果你愿意,可以自定义对象),通过这个例子中的函数;重要的是你理解Python mutable types
【解决方案2】:

仅仅创建字典比深度复制要高效得多:

In [3]: %%timeit
   ...: _premium_per_month = {1: [0.0, []], 2: [0.0, []], 2: [0.0, []], 3: [0.0, []], 4: [0.0, []], 5: [0.0, []], 
   ...:         6: [0.0, []], 7: [0.0, []], 8: [0.0, []],
   ...:         9: [0.0, []], 10: [0.0, []], 11: [0.0, []], 12: [0.0, []]}
   ...: 
100000 loops, best of 3: 2.13 µs per loop

In [4]: _premium_per_month = {1: [0.0, []], 2: [0.0, []], 2: [0.0, []], 3: [0.0, []], 4: [0.0, []], 5: [0.0, []], 
   ...:         6: [0.0, []], 7: [0.0, []], 8: [0.0, []],
   ...:         9: [0.0, []], 10: [0.0, []], 11: [0.0, []], 12: [0.0, []]}

In [5]: 

In [5]: from copy import deepcopy

In [6]: timeit d = deepcopy(_premium_per_month) 
10000 loops, best of 3: 74.6 µs per loop

所以不要使用模板,而是使用引用和深拷贝在函数中创建字典,这样你每次都会得到一个新对象:

def test():
  premium_per_month = {1: [0.0, []], 2: [0.0, []], 2: [0.0, []], 3: [0.0, []], 4: [0.0, []], 5: [0.0, []], 
    6: [0.0, []], 7: [0.0, []], 8: [0.0, []],
    9: [0.0, []], 10: [0.0, []], 11: [0.0, []], 12: [0.0, []]}

【讨论】:

    猜你喜欢
    • 2015-01-13
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    相关资源
    最近更新 更多