为什么在这里使用嵌套循环时,Python会打印出奇怪的结果?

3
我得到了一个字符串数组,并且我想将每个单独的字符串拆分成单个字符并将它们存储在一个独立的二维数组中。我编写了以下代码:-
# The given array
grid = ['1112', '1912', '1892', '1234']

# Creating a new 2D array
mat = [[None]*len(grid)]*len(grid)
for i in range(0,len(grid)):
    for j in range(0,len(grid)):
        mat[i][j] = grid[i][j]
print(mat)

但是这样做会给我的二维数组mat带来奇怪的值。每一行都被打印成['1','2','3','4'],但这应该只是最后一行的值。

如果有人能回答我的疑问,我将不胜感激。

3个回答

3
mat = [[None]*len(grid)]*len(grid)

该语句创建了一个关系型的二维数组(矩阵),所以当你更新一行时,它会同时更新所有其他行。

你应该使用这个来创建一个空的二维数组:

mat = [[None for i in len(grid)] for j in range(len(grid))]

正如@marc评论的那样,您也可以将一个列表推导式作为宽度=高度传递在这里

mat = [[None]*len(grid) for _ in range(len(grid))]

1
你可以安全地跳过列表推导式的一个步骤,使用 mat = [[None]*len(grid) for i in range(len(grid)] - Marc
@Marc 嗯,好的,我会将其添加在一起。如果后来他们需要一个宽度与高度不同的矩阵,他们仍然需要进行2个列表推导。 - Gugu72

1

将乘法运算符用于列表会在内存中创建相同的引用,代码已修复如下:

# The given array
grid = ['1112', '1912', '1892', '1234']

# Creating a new 2D array
# mat = [[None]*len(grid)]*len(grid)
mat = []
for i in range(len(grid)):
    t = []
    for j in range(len(grid)):
        t.append(None)
    mat.append(t)

for i in range(0,len(grid)):
    for j in range(0,len(grid)):
        mat[i][j] = grid[i][j]
print(mat)

1
这个方法可以运行,但是比我的答案处理时间更长,使用列表推导式的方法也更易读。 - Gugu72

1

我必须承认,在这个问题上很容易感到困惑。

假设len(grid) = 2,那么我们得到mat = [[None]*2]*2

这里mat[0]指向mat[1]的同一个对象,因为*2给出了两个指向同一数组的指针。您可以使用for _ in range(2)来创建两个不同的对象- [[None]*len(grid) for _ in range(len(grid))]

我们可以使用id打印对象的地址进行验证:

>>> mat = [[None]*2]*2
>>> id(mat[0])
76447616
>>> id(mat[1])
76447616
>>> grid = [0, 0]
>>> x = [[None]*len(grid) for _ in range(len(grid))]
>>> id(x[0])
76457744
>>> id(x[1])
76391968

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接