在Python2.7中,为什么grid=[[[A";]*5]*5不同于grid=[]grid.append[…]

在Python2.7中,为什么grid=[[[A";]*5]*5不同于grid=[]grid.append[…],python,list,python-2.7,append,python-2.x,Python,List,Python 2.7,Append,Python 2.x,我正在尝试构建一个游戏板,它是Python2.7中的5x5网格,表示为二维列表。 我试着将它写成board=[[“O”]*cols]*rows(cols和rows已经声明为5),但当我试图编辑索引处的值时,它会更改整行。比如说 cols = 5 rows = 5 board = [["O"]*cols]*rows 这张照片是: [['O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O'], ['

我正在尝试构建一个游戏板,它是Python2.7中的5x5网格,表示为二维列表。 我试着将它写成board=[[“O”]*cols]*rows(cols和rows已经声明为5),但当我试图编辑索引处的值时,它会更改整行。比如说

cols = 5
rows = 5
board = [["O"]*cols]*rows
这张照片是:

[['O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O']]
现在,当我尝试更改索引的值时,如:

board[1][1] = "X"
它打印:

[['O', 'X', 'O', 'O', 'O'], ['O', 'X', 'O', 'O', 'O'], ['O', 'X', 'O', 'O', 'O'], ['O', 'X', 'O', 'O', 'O'], ['O', 'X', 'O', 'O', 'O']]
我只想更改第1行第1列的值

我还尝试了以下几点:

board = []
for i in xrange(5):
    board.append(["O"]*cols)

这一个像我想要的那样工作。我想了解的是区别是什么?

您的第一个表达式是创建指向单个列表对象的指针列表。因此,当您更新一个元素时,它在任何地方都会发生更改。

如果您计算下面的表达式,您将看到第一个示例返回True,而另一个示例返回False。两个列表实际上都指向内存中的同一个列表

board[0]是board[1]

如果您确实希望有一个简短的版本来创建不同的新列表,那么这个版本也可以正常工作

board = [["O"]*cols for y in range(rows)]

因为Python没有隐式复制东西的习惯
[x]*5
表示“一个由5个事物组成的列表,每个事物都是
x
”。如果你改变一个,你就改变了它们,因为它们都是
x
——而不是
x
的副本

使用
.append()
时,会强制复制,因为每次通过循环时,都会从头创建要追加的值


是的,
[“O”]*5
生成一个包含5个内容的列表,每个内容都是相同的
“O”
。然而,这实际上并不相关;“一个不同的
“O”
”这样的事情是没有意义的,因为您不能更改
“O”
——无论您对名为
“O”
的变量做什么,
“O”
仍然是
“O”

请注意,在Python中列表是从0索引的。因此,第1行第1列将由
board[0][0]
返回。顺便说一句,这不是2.x特定的:它一直是这样工作的,而且几乎可以肯定总是这样工作的。使用该函数可能也很有趣:
print id(board[0]
print id(board[1])