关于python:更改一个列表中的元素会更改多个列表

Changing an element in one list changes multiple lists

本问题已经有最佳答案,请猛点这里访问。

我有一张单子,上面写着:mysolution

1
2
3
4
5
>>>mySolution
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> mySolution[0][0] = 1    
>>> mySolution
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]

预期产量:

1
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

为什么列表中的所有第一个元素都被更改为1?我只想将第一个列表的第一个元素更改为1。


重要的是您如何创建原始的mysolution列表。看起来,它包含了同一个列表的四倍,这就是为什么一次更改会使它在所有四个位置都发生更改。

要初始化这样的独立零填充列表,可以执行以下操作:

1
mysolution = [[0] * 4 for i in range(4)]


很可能您创建了这样的列表:

1
2
mySolution = [0]*4
mySolution = [mySolution]*4

或同等:

1
mySolution = [[0]*4]*4

以上任何一个片段都将创建一个包含四个子列表的列表,这些子列表是完全相同的子列表的副本,因此对一个子列表的任何修改都将反映在其他子列表上——它们是一个且相同的子列表。解决方案是创建四个不同的子列表:

1
mySolution = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

或者短一点:

1
mySolution = [[0]*4 for _ in xrange(4)]


请注意,这样做很好:

1
2
3
4
5
6
mySolution = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
mySolution[0][0] = 1    
print mySolution

>>>
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

这完全取决于您如何初始化solution。这

1
2
3
mySolution = [[0, 0, 0, 0]]*4
mySolution[0][0] = 1    
print mySolution

给予

1
2
3
>>>
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
>>>

因为这里mysolution中的每个数组[0, 0, 0, 0]都是[[0, 0, 0, 0]]*4中初始化数组[0, 0, 0, 0]的副本。如果更改第一个数组的第一个元素,那么它的副本也会更改。

使用此初始化mySolution = [[0, 0, 0, 0] for x in range(4)]时,您不会复制数组,而是将[0,0,0,0]追加四次,从而得到预期的结果。


因为所有包含的列表实际上都是相同的列表。当你这样做的时候:

1
2
l = [0, 0, 0, 0]
my_solution = [l, l, l]

那么,my_solution[0]my_solution[1]my_solution[2]是对同一对象的引用(l)。

如果您在一个位置修改列表,它将在任何地方更改。这是因为列表是可变对象。

相反,使用多个列表:

1
2
3
4
l1 = [0, 0, 0, 0]
l2 = [0, 0, 0, 0]
l3 = [0, 0, 0, 0]
my_solution = [l1, l2, l3]

按预期工作。