所以我试图在python中使用二维数组重新创建生命游戏,但我偶然发现了一个非常奇怪的错误。为了创建这个数组,我使用了这个函数:
def MakeGrid(height):
gridY = []
grid = []
for i in range(height):
gridY.append(False)
for i in range(height):
grid.append(gridY)
return(grid)
但是有一个非常奇怪的错误,如果我试图改变一个假到一个真只有1点,它改变对角线各处。下面是一个例子:
grid = MakeGrid(2) # grid is now [[False,False], [False,False]]
grid[0][0] = True #grid should be [[True, False], [False, False]], but it's actually [[True, False], [True, False]]
我真的不知道是什么原因引起的,但它真的很烦人,我真的很需要一些帮助。
这不是一个bug,而是当一次又一次地添加完全相同的列表时的预期行为。由于您将相同的列表(gridY
)附加到grid
中,因此它们都共享相同的内存grid
内;这意味着在grid
内部的任何列表中的一个元素(或多个)的更改将适用于grid
内部的所有其他列表,因为它们是相同的对象.
看下面的句子:
x = [1, 2, 3]
y = []
y.append(x)
y.append(x)
y[0] == x # True (same list contents)
y[0] is x # Also True! (same memory, exact same list)
因此,您需要添加该列表的副本,该副本不共享相同的内存/标识,但使用.copy()
具有相同的内容。发生的事情是grid
数组在内存中存储了许多指向相同gridY
部分的指针。当你改变一个指针时,整个gridY
都会改变。因此,当您将gridY
中的一个False
更改为True
时,整个gridY
都会发生变化。你可以使用
def MakeGrid(height):
gridY = []
grid = []
for i in range(height):
gridY.append(False)
for i in range(height):
grid.append(gridY[:])
return(grid)
或
def MakeGrid(height):
gridY = []
grid = []
for i in range(height):
gridY.append(False)
for i in range(height):
grid.append(gridY.copy())
return(grid)
正如@Epsi95提到的
这是一个混叠问题。列表在python中是一个对象,这里你已经将gridY
减速为一个列表对象,并且不断地更改它。通过不断将其追加到grid
,您不会创建不同长度的新对象,而是多次添加相同的对象。当您尝试更改一次时,您将在整个grid