在密钥中共享defaultdict中的Dict

Isa*_*aac 4 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'}}})
Run Code Online (Sandbox Code Playgroud)

请注意,这两个字典v都设置v2为.这是为什么?如何在没有太多性能开销的情况下改变这种行为?

agf*_*agf 6

当你这样做时,dict(defaults)你没有复制内部字典,只是另外引用它.因此,当您更改该字典时,您将在所引用的任何位置看到更改.

你需要deepcopy在这里避免这个问题:

import copy
from collections import defaultdict
defaults = {'a': 1, 'b': {}}
dd = defaultdict(lambda: copy.deepcopy(defaults))
Run Code Online (Sandbox Code Playgroud)

或者您不需要在连续调用中使用相同的内部可变对象,而不是重复引用defaults:

dd = defaultdict(lambda: {'a': 1, 'b': {}})
Run Code Online (Sandbox Code Playgroud)