Python - 浅拷贝是不够的。 Deepcopy 或任何提高速度的替代方法?
Python - shallow copy is not enough. Deepcopy or any alternative to improve speed?
我有这个 "template" 字典:
_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 还是有一些 tips/tricks 来替代 better/faster 副本或模式(也许我的模式是错误的)?
为了更好地理解它的作用,请查看此方法(已简化以仅显示核心问题)
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 是解决此问题的正确方法还是我应该更改其他内容?
我想如果我把那个模板方法放在一起会更有效率(注意。在这里显示我在评论中提到的那个对象,所以它会显示为什么我使用值作为列表,它被称为 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
只创建字典比深度复制更有效:
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, []]}
我有这个 "template" 字典:
_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 还是有一些 tips/tricks 来替代 better/faster 副本或模式(也许我的模式是错误的)?
为了更好地理解它的作用,请查看此方法(已简化以仅显示核心问题)
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 是解决此问题的正确方法还是我应该更改其他内容?
我想如果我把那个模板方法放在一起会更有效率(注意。在这里显示我在评论中提到的那个对象,所以它会显示为什么我使用值作为列表,它被称为 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
只创建字典比深度复制更有效:
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, []]}