python引用,嵌套dicts和'del'产生意外行为

时间:2017-07-14 16:12:32

标签: python dictionary

这更令人感兴趣。 我观察到以下行为,并想知道为什么/如何发生这种情况(在python 2.7.3& python 3.4.1中尝试过)

ph = {1:0, 2:0}
d1 = {'a':ph, 'b':ph}
d2 = {'a':{1:0,2:0},{'b':{1:0,2:0}}
>>> d1
{'a':{1:0,2:0},{'b':{1:0,2:0}}

所以d1和d2是一样的。 但是当使用del或替换值时会发生这种情况

>>> del d1['a'][1]
>>> d1
{'a':{2:0}, 'b':{2:0}}
>>> del d2['a'][1]
>>> d2
{'a':{2:0},{'b':{1:0,2:0}}

d2的行为符合预期,但d1(ph)中的嵌套字典似乎工作方式不同。 是因为python中的所有变量都是引用吗? 如果我不能为每个实例指定占位符字典,是否有解决方法?

谢谢!

2 个答案:

答案 0 :(得分:3)

尝试使用pythontutor。如果您将代码放入其中,您将看到:

enter image description here

您可以看到,您怀疑d1中的词典是对同一个对象ph的引用。

这意味着,当您del d1['a'][1]时,它会真正删除ph中的某个键,以便您获得此信息:

enter image description here

要解决此问题,您需要使用d1字典的副本初始化ph,如此处其他答案所述......

答案 1 :(得分:1)

d1中的两个键都指向相同的引用,因此当您从d1删除时,无论您是ph还是d1['a'],都会影响d1['b'] - 你到了同一个地方。

另一方面,

d2实例化两个单独的对象,因此您只影响示例中的一个。

您的解决方法将.deepcopy()用于d1中的第二次引用。

d1 = {'a':ph, 'b':ph.deepcopy()}

(在这个例子中你真的不需要深度复制 - copy()就足够了 - 但是如果ph更复杂,你会看到上面链接的文档。)