二维数组中Square对象y值莫名全部变为12的原因排查
问题:二维数组中所有Square对象的y值异常变为12
创建Square对象的二维数组时,首次循环创建并打印x、y值均符合预期,但后续访问网格对象时,所有Square的y值都变成了12,x值正常。相关代码如下:
class Square(): def __init__(self, row, col, x, y, value): #self.color = color self.row = row self.col = col self.x = x self.y = y self.value = value drawWall = False drawPath = False SQUARE_WIDTH = 6 SQUARE_HEIGHT = 6 GRID_SIZE_HEIGHT = 3 GRID_SIZE_WIDTH = 3 def createGrid(): print("this is the created grid \n ==============================================================") grid = [[None]* GRID_SIZE_HEIGHT] * GRID_SIZE_WIDTH y = 0 for i in range(GRID_SIZE_WIDTH): x = 0 for j in range(GRID_SIZE_HEIGHT): grid[i][j] = Square(i, j, x, y, 2) print(' [',i,"][", j,']:', "x", x, "y", y, end = '') x += SQUARE_WIDTH y += SQUARE_HEIGHT print() # printing the grid again for testing. Every y is 12 print("============================================================") print("Why are all ys all 12????") for i in range(GRID_SIZE_WIDTH): for j in range(GRID_SIZE_HEIGHT): xr = grid[i][j].x yr = grid[i][j].y print(' [',i,"][", j,']:', "x", xr, "y", yr, end = '') print() print("====================================================") return grid newGrid = createGrid()
原因分析
问题出在二维数组的初始化语句:
grid = [[None]* GRID_SIZE_HEIGHT] * GRID_SIZE_WIDTH
使用* GRID_SIZE_WIDTH复制列表时,并没有生成独立的子列表,而是让grid中的每一行都指向同一个子列表对象。也就是说,grid[0]、grid[1]、grid[2]其实是同一个列表的引用。
循环过程中:
- 当
i=0时,给子列表的三个位置赋值了y=0的Square对象; - 当
i=1时,修改的还是同一个子列表,把原来的Square替换成了y=6的; - 当
i=2时,再次替换为y=12的Square对象。
最终,所有行的Square都是最后一次循环(y=12)创建的对象,因此后续访问时所有y值都显示为12。而x值看似正常,是因为最后一次循环中x的取值恰好对应了每个列的预期值,但本质上所有行的子列表都是同一个,内容完全一致。
解决方案
将二维数组的初始化方式改为列表推导式,确保每一行都是独立的新列表:
grid = [[None for _ in range(GRID_SIZE_HEIGHT)] for _ in range(GRID_SIZE_WIDTH)]
这样循环时,每一行grid[i]都是全新的列表,不会互相干扰,创建的Square对象会正确保存在对应的位置,后续访问时y值就会符合预期。
内容的提问来源于stack exchange,提问作者Cerberus
相关产品推荐
相关产品推荐

