你能用 Python defaultdict 和 autovivification 解释这种行为吗

Can you explain this behavior with Python defaultdict and autovivification

我不确定我是否在这里遗漏了一些微不足道的东西,但我终其一生都无法弄清楚下面的代码是如何设法提供它的输出的。

import collections

tree = collections.defaultdict(dict)
tree[0][1] = tree[1]
print tree
tree[1][2] = tree[2]
print tree

这是神奇的输出:

defaultdict(<type 'dict'>, {0: {1: {}}, 1: {}})
defaultdict(<type 'dict'>, {0: {1: {2: {}}}, 1: {2: {}}, 2: {}})

第一行输出完全有意义。然后考虑赋值 tree[1][2] = tree[2] 及其后续输出。

我知道条目 2: {} 是通过计算 RHS 表达式 tree[2].

创建的

我还了解到条目 1: {2: {}} 是通过评估 LHS 表达式 tree[1][2] 并将其分配给 RHS 的值而创建的。

我不明白的是,在没有引用 tree[0] 的情况下,字典条目 0: {1: {}} 是如何更新为 0: {1: {2: {}}} 的。

因为当您执行 tree[0][1] = tree[1] 时,tree[0][1] 引用与 tree[1] 相同的对象,因此如果 tree[1] 内部发生任何更改,它也会反映在 tree[0][1].

而且,当您执行 tree[1][2] 时,您实际上是在 tree[1] 内部进行更改,而不是使 tree[1] 引用新对象。

示例,在您更改后尝试这样做 -

>>> tree[1]['blah'] = 'Hello'
>>> print(tree)
defaultdict(<class 'dict'>, {0: {1: {2: {}, 'blah': 'Hello'}}, 1: {2: {}, 'blah': 'Hello'}, 2: {}})

只有当你做类似 - tree[1] = <somethingelse> 的事情时,你才会 tree[1] 引用一个新对象,在这种情况下它不会反映在 tree[0][1] 中。

很多对象(不是基元)被存储为引用,而不是值。所以如果你把a赋值给b,那么改变a,b也会改变。