为什么更改一个 Python 列表元素会更改所有其他元素?

问题描述 投票:0回答:2

我有一些代码,我制作了一个字典,每个值都是列表

[0,0]
。我发现增加任何列表索引都会增加每个值的相应索引;即
d[key][0] += 1
会增加彼此列表的 0 索引。

我认为 Python 对列表的浅复制是罪魁祸首,因为我的字典是使用

dict.fromkeys(keys, [0,0])
构建的。但是,在列表中使用
copy.deepcopy
时,我遇到了同样的问题。 然后我尝试了字典理解:
{key:[0,0] for key in keys}
。这正如我所期望的那样;修改一个列表不会影响其他列表。

既然我找到了这个问题的解决方案,我的实际问题是为什么是这种情况。看来我要么误解了

deepcopy
的工作原理,要么与当前的问题无关,但我不知道还有什么会导致这种情况。

这是重现该行为的完整片段:

import copy
keys = [i for i in range(5)]
l = [0,0]
d = dict.fromkeys(keys, copy.deepcopy(l))
#d = {key:[0,0] for key in keys} # this approach works as expected
d[0][0] += 1
print(d)
# expected: {0: [1, 0], 1: [0, 0], 2: [0, 0], 3: [0, 0], 4: [0, 0]}
# actual: {0: [1, 0], 1: [1, 0], 2: [1, 0], 3: [1, 0], 4: [1, 0]}
python dictionary deep-copy
2个回答
0
投票

您只制作列表的一份副本,并将其用于字典中的每个值。函数参数仅计算一次,结果将传递给函数。所以当你写的时候

d = dict.fromkeys(keys, copy.deepcopy(l))

它实际上相当于

temp = copy.deepcopy(l)
d = dict.fromkeys(keys, temp)

改用字典理解,这样您就可以为每个元素创建一个新副本。

d = {key: copy.deepcopy(l) for key in keys}

0
投票

在这种情况下,

deepcopy
无助于解决问题,它是
dict.fromkeys
功能。 来自 https://docs.python.org/3/library/stdtypes.html#dict.fromkeys

的文档

所有值仅引用一个实例,因此值作为可变对象(例如空列表)通常没有意义。要获得不同的值,请使用字典理解。

您将单个列表传递给 fromkeys 作为 value 参数。它仍然只是一个列表

所以看来你的字典理解是推荐的方法。

© www.soinside.com 2019 - 2024. All rights reserved.