修改 python 中的元素嵌套列表

modifying the elements nested lists in python

谁能解释一下这背后发生了什么?我试图搜索类似的行为,但大多数问题都是关于迭代嵌套列表的

r1=[0 for i in range(3)]
result=[r1 for j in range(3)]
result[0][0]=4 # it will edit all the 0th elements of the sublists
print(result)

r1=[0 for i in range(3)]
result=[r1 for j in range(3)]
result[1][0]=4 # it will edit all the 0th elements of the sublists
print(result)

r1=[0 for i in range(3)]
result=[r1 for j in range(3)]
result[0][1]=4 # it will edit all the 1st elements of the sublists
print(result)

result = [[0 for x in range(3)] for y in range(3)]
result[0][0]=4
print(result) # it will edit only the first element of first sublist

输出是

[[4, 0, 0], [4, 0, 0], [4, 0, 0]]
[[4, 0, 0], [4, 0, 0], [4, 0, 0]]
[[0, 4, 0], [0, 4, 0], [0, 4, 0]]
[[4, 0, 0], [0, 0, 0], [0, 0, 0]]

问题出在您构建嵌套列表的方式上。以下:

r1=[0 for i in range(3)]
result=[r1 for j in range(3)]

创建一个包含 3 个 r1 的列表。而不是 3 个不同列表的列表,这就是为什么当您修改 result[j] 中的任何一个时,它会修改 r1,因此会修改所有其他列表 result[j]。正如其他人所指出的,这与 described here, with a different expression: result = [r1] * 3

完全相同

另一方面,在上次测试中,您创建了您所期望的,一个包含 3 个不同列表的列表:

result = [[0 for x in range(3)] for y in range(3)]

您可以使用 r1:

来做同样的事情
result = [[x for x in r1] for y in range(3)]

这里的内部“循环”只是将 r1 的元素复制到一个新的(不同的)列表中:

r1 = [0 for i in range(3)]
result = [[x for x in r1] for y in range(3)]
result[0][0] = 4
print(result)

打印:

[[4, 0, 0], [0, 0, 0], [0, 0, 0]]

您可以在这个更简单的示例中观察到原始问题,其中对 r1 的修改也会影响 r2:

r1 = [0 for i in range(3)]
r2 = r1 
r1[0] = 4
print(r2)

此行为背后的原因很简单,r1r2 是同一对象的两个名称。当我们写 r1[0] = 4 时,我们不会更改 r1 的值,我们会更改 r1 引用的列表的值(或 如果愿意,指向*)。这不是 python 特有的,任何可以修改“in-place”的数据结构都会遇到这个“问题”(我建议阅读可变数据结构与不可变数据结构以更好地理解这里发生的事情) .