我在defaultdict中有一个字典。我注意到字典是在键之间共享的,因此它需要最后一次写入的值。我该如何隔离这些词典?
>>> from collections import defaultdict
>>> defaults = [('a', 1), ('b', {})]
>>> dd = defaultdict(lambda: dict(defaults))
>>> dd[0]
{'a': 1, 'b': {}}
>>> dd[1]
{'a': 1, 'b': {}}
>>> dd[0]['b']['k'] = 'v'
>>> dd
defaultdict(<function <lambda> at 0x7f4b3688b398>, {0: {'a': 1, 'b': {'k': 'v'}}, 1:{'a': 1, 'b': {'k': 'v'}}})
>>> dd[1]['b']['k'] = 'v2'
>>> dd
defaultdict(<function <lambda> at 0x7f4b3688b398>, {0: {'a': 1, 'b': {'k': 'v2'}}, 1: {'a': 1, 'b': {'k': 'v2'}}})
请注意,两个词典的v
都设置为v2
。这是为什么?以及如何在没有太多性能开销的情况下改变这种行为?
答案 0 :(得分:6)
当您执行dict(defaults)
时,您不会复制内部词典,只需另外引用它。因此,当您更改该字典时,您将会在其引用的任何地方看到更改。
您需要deepcopy
来避免此问题:
import copy
from collections import defaultdict
defaults = {'a': 1, 'b': {}}
dd = defaultdict(lambda: copy.deepcopy(defaults))
或者你不需要在连续调用中使用相同的内部可变对象,而不是重复引用defaults
:
dd = defaultdict(lambda: {'a': 1, 'b': {}})
答案 1 :(得分:2)
您的值都包含对defaults
中同一对象的引用:您重建外部字典,但不重建内部字典。只需创建一个创建新的独立对象的函数:
def builder():
return {'a': 1, 'b': {}}
dd = defaultdict(builder)