错误 appending/concat。在嵌套 Python 字典的底部列出

Incorrectly appending/concat. to list at bottom of nested Python dictionary

当我创建一个嵌套字典结构时,我 运行 遇到了一个问题,当我试图将一个项目附加到嵌套字典中的列表时,它会将该项目附加到我的所有级别的所有列表中具有相应最终键的嵌套字典。

d = {"p": [], "d": []}
d = {value: dict(d) for value in [1,2,3]}
d = {value: dict(d) for value in ["h", "i"]}

d
Out[14]: 
{'h': {1: {'p': [], 'd': []}, 2: {'p': [], 'd': []}, 3: {'p': [], 'd': []}},
 'i': {1: {'p': [], 'd': []}, 2: {'p': [], 'd': []}, 3: {'p': [], 'd': []}}}

当我开始使用 append() 填充我的“底层”词典列表时,会发生这种情况:

d["h"][1]["p"].append("Please Help")

d
Out[16]: 
{'h': {1: {'p': ['Please Help'], 'd': []},
  2: {'p': ['Please Help'], 'd': []},
  3: {'p': ['Please Help'], 'd': []}},
 'i': {1: {'p': ['Please Help'], 'd': []},
  2: {'p': ['Please Help'], 'd': []},
  3: {'p': ['Please Help'], 'd': []}}}

如上所示,字符串被附加到 d 中具有最终键 'p' 的每个列表。使用列表串联会产生类似但不同的结果:

d = {"p": [], "d": []}
d = {value: dict(d) for value in [1,2,3]}
d = {value: dict(d) for value in ["h", "i"]}

d["h"][1]["p"] = d["h"][1]["p"] + ["Please Help"]

d
Out[23]: 
{'h': {1: {'p': ['Please Help'], 'd': []},
  2: {'p': [], 'd': []},
  3: {'p': [], 'd': []}},
 'i': {1: {'p': ['Please Help'], 'd': []},
  2: {'p': [], 'd': []},
  3: {'p': [], 'd': []}}}

在这里,字符串被添加到共享相同的第 2 级和第 3 级密钥(分别为 1 和 'p')的列表中。我不明白发生了什么,我们将不胜感激。这是在 Python 3.7.

就像@Mark 说的,你需要使用复制...

from copy import deepcopy as dc

d = {"p": [], "d": []}
d = {value: dc(d) for value in [1,2,3]}
d = {value: dc(d) for value in ["h", "i"]}

d["h"][1]["p"].append("Please Help")

print(d)
#{'h': {1: {'p': ['Please Help'], 'd': []}, 2: {'p': [], 'd': []}, 3: {'p': [], 'd': []}}, 'i': {1: {'p': [], 'd': []}, 2: {'p': [], 'd': []}, 3: {'p': [], 'd': []}}}

当您执行 d = {value: dict(d) for value in [1,2,3]} 时,您不会在 d 中创建三个不同的词典。您将同一本词典重复了三次。 d = {value: dict(d) for value in ["h", "i"]} 同样如此。因此,当您执行 d["h"][1]["p"].append("Please Help") 时,您是将 'Please Help' 附加到一个字典。由于另一个“底层”字典是同一个字典,您会一遍又一遍地看到相同的字符串。

打个比方,你可以把每个变量想象成一个盒子,上面有一个数字。当您执行 d = {value: dict(d) for value in [1,2,3]} 时,您将同一个框 number 放入字典三次,而不是创建三个不同的框。当您告诉 Python 更改“第一个”框的值时,它会转到具有该框编号的框,并更改该框中的内容。由于所有“其他”框都指的是同一个框,因此当您查看这些“其他”框时所看到的内容也会发生变化。

您可以通过 {value: dict(d).copy() for value in [1,2,3]}.

来解决这个问题