Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有奇怪填充行为的python嵌套字典_Python_Dictionary - Fatal编程技术网

具有奇怪填充行为的python嵌套字典

具有奇怪填充行为的python嵌套字典,python,dictionary,Python,Dictionary,我在Python2.7.12嵌套dict中看到了一个奇怪的行为,我不明白为什么会发生这种情况。假设我有这本字典: list_1 = ['5', '10', '15', '30'] dict_1 = { i:[] for i in list_1 } 现在我创建一个嵌套的dict,如下所示: list_2 = ['a', 'b'] dict_2 = { i:dict_1 for i in list_2 } 还有一个嵌套的dict,如下所示: dict_3 = { i:{j:[] for j in

我在Python2.7.12嵌套dict中看到了一个奇怪的行为,我不明白为什么会发生这种情况。假设我有这本字典:

list_1 = ['5', '10', '15', '30']
dict_1 = { i:[] for i in list_1 }
现在我创建一个嵌套的dict,如下所示:

list_2 = ['a', 'b']
dict_2 = { i:dict_1 for i in list_2 }
还有一个嵌套的dict,如下所示:

dict_3 = { i:{j:[] for j in list_1} for i in list_2 }
如果在我填写前打印,则dict_3和dict_2是相同的:

{'a': {'15': [], '10': [], '30': [], '5': []}, 'b': {'15': [], '10': [], '30': [], '5': []}}
但是当我把字典填好的时候,比如:

dict_2['a']['5'].append(1)
dict_3['a']['5'].append(1)
dict_2有一个我不想要的行为,在“a”和“b”中填充元素“5”:

{'a': {'15': [], '10': [], '30': [], '5': [1]}, 'b': {'15': [], '10': [], '30': [], '5': [1]}}
dict_1具有我想要的行为,只在“a”中填充元素“5”:

{'a': {'15': [], '10': [], '30': [], '5': [1]}, 'b': {'15': [], '10': [], '30': [], '5': []}}

我猜想在dict\u2中嵌套dict_u1只是到该字典的链接,而dict_3是一个真正嵌套的字典。对吗?无论如何,我发现python dicts的这种用法很容易引起误解,如果它不是bug,为什么python中需要这种行为?

赋值从不复制数据。只是在理解中看作业有点难

dict_2 = {i:dict_1 for i in list_2}
相当于

dict_2 = {}
for i in list_2:
    dict_2[i] = dict_1 # the assignments I'm talking about
现在您有了
dict_2[i]
作为所有
i
dict_1
参考。不复制任何数据。内存中有一个值为
{'15':[],'10':[],'30':[],'5':[]}
的字典,它的名字正好是
dict_1
,但现在也被
dict_2
中的所有键引用。(内存中可以有多个相同值的名称/引用。)

如果你想要字典的真实深度副本,使用

>>> from copy import deepcopy
>>> dict_2 = {i:deepcopy(dict_1) for i in list_2}
>>> dict_2['a']['5'].append(1)
>>> dict_2
{'a': {'10': [], '30': [], '15': [], '5': [1]}, 'b': {'10': [], '30': [], '15': [], '5': []}}

同样的逻辑也适用于dict_3

为什么你认为这很奇怪
dict_2
包含对同一
dict_1
的两个引用,而
{}
comprehension每次被调用时都会创建一个新的字典。@dhke对于那些来自可以复制数据的语言的人来说,这很奇怪。@timgeb Point接受了。@dhke觉得很奇怪,因为我是调试时最后一个想到的人。@timgeb所说的是正确的,但由于Python涵盖了指针,我花了一段时间才明白我在做一个引用,而不是创建一个新的dict。现在这更清楚了,我已经对列表和dict做了更多的测试,是的,我不明白赋值实际上是引用。无论如何,这仍然有点误导,因为:
a=0
<代码>b=a<代码>a=10<代码>打印一份<代码>打印b;在这种情况下,输出将是10和0,这意味着有赋值时会有一个副本!我希望代码是可读的。@ianmartipostoma不,在Python中,赋值从不复制数据。这是真的。总是。在您的示例中就是这样:您将名称
a
绑定到值
0
。然后将另一个名称,
b
绑定到内存中的同一个对象。然后将名称
a
重新绑定到另一个值。此操作不影响名称
b
指向的内容。在这个过程中没有复制任何数据。因此,在我的上一个示例中,我做了与列表中I的dict_2['b']={I:[]相同的操作,通过这种方式,我将
dict_2['b']
元素重新绑定到另一个值,而无需重新绑定
dict_2['a']
元素。好啊非常感谢,我会记住的!