为什么这个 python 列表只存储最后输入的元素

Why is this python list storing only the last input elements

请解释以下行为

import sys
input=sys.stdin.readline

for _ in range(int(input())):
    n=int(input())
    m=int(input())
    vertices=[[0, 0]]*n
    edges=[[0, 0, 0]]*m
    for i in range(m):
        edges[i][0], edges[i][1], edges[i][2]=list(map(int, input().split()))
    for i in range(m):
        print(edges[i][0], edges[i][1], edges[i][2])

当以下输入输入程序时:

1
5
7
1 2 1
2 3 2
2 4 6
5 2 1
5 1 3
4 5 2
3 4 3

正在生成此输出:

3 4 3
3 4 3
3 4 3
3 4 3
3 4 3
3 4 3
3 4 3

为什么只有最后的输入被存储在所有元素中?

让我们看看这个解释器会话:

>>> a = [[0,0,0]] * 5
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]

这实际上是 Python 中的一个常见陷阱。代码翻译成这样

inner = [0, 0, 0]
a = [inner, inner, inner, inner, inner]

这种写法更清楚地表明您实际上创建了一个列表,其中所有条目都指向同一个对象(inner).

解决这个问题的一种方法是使用列表理解,这样将为每个列表条目创建一个新的内部列表:

vertices=[[0, 0] for _ in range(n)]
edges=[[0, 0, 0] for _ in range(m)]

另一个修复方法是使用 numpy 并使用 numpy.zeros(n, 2) 声明二维矩阵。 Numpy 通常对 math/numerics-intensive 应用程序有用。