我正在使用itertools.tee
制作生成器的副本,这些生成器会产生字典并将迭代的字典传递给我无法控制的函数,并且可能会修改字典。因此,我想将字典的副本传递给函数,但是所有的tees都只产生对同一个实例的引用。
以下简单示例说明了这一点:
import itertools
original_list = [{'a':0,'b':1}, {'a':1,'b':2}]
tee1, tee2 = itertools.tee(original_list, 2)
for d1, d2 in zip(tee1, tee2):
d1['a'] += 1
print(d1)
d2['a'] -= 1
print(d2)
输出结果为:
{'b': 1, 'a': 1}
{'b': 1, 'a': 0}
{'b': 2, 'a': 2}
{'b': 2, 'a': 1}
虽然我想:
{'b': 1, 'a': 1}
{'b': 1, 'a': -1}
{'b': 2, 'a': 2}
{'b': 2, 'a': 0}
当然,在这个例子中有很多方法可以轻松地解决这个问题,但由于我的具体用例,我需要一个版本itertools.tee
来存储所有迭代对象的副本。 tees而不是对原文的引用。
在Python中是否有直接的方法来执行此操作,或者我是否必须以非原生的方式重新实现itertools.tee
,因此效率低下?
答案 0 :(得分:1)
无需返工tee
。只需将tee
生成的每个生成器包装在map(dict, ...)
生成器中:
try:
# use iterative map from Python 3 if this is Python 2
from future_builtins import map
except ImportError:
pass
tee1, tee2 = itertools.tee(original_list, 2)
tee1, tee2 = map(dict, tee1), map(dict, tee2)
在迭代时,这会自动生成每个字典的浅表副本。
演示(使用Python 3.6):
>>> import itertools
>>> original_list = [{'a':0,'b':1}, {'a':1,'b':2}]
>>> tee1, tee2 = itertools.tee(original_list, 2)
>>> tee1, tee2 = map(dict, tee1), map(dict, tee2)
>>> for d1, d2 in zip(tee1, tee2):
... d1['a'] += 1
... print(d1)
... d2['a'] -= 1
... print(d2)
...
{'a': 1, 'b': 1}
{'a': -1, 'b': 1}
{'a': 2, 'b': 2}
{'a': 0, 'b': 2}