在密钥中共享defaultdict中的Dict

时间:2014-07-14 21:27:59

标签: python dictionary

我在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。这是为什么?以及如何在没有太多性能开销的情况下改变这种行为?

2 个答案:

答案 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)