【问题标题】:In Python 2.7 why is grid = [["A"]*5]*5 different than grid = [] grid.append[...]在 Python 2.7 中,为什么 grid = [["A"]*5]*5 不同于 grid = [] grid.append[...]
【发布时间】:2012-09-24 09:27:24
【问题描述】:

我正在尝试在 python 2.7 中构建一个 5x5 网格的游戏板,表示为二维列表。 我尝试将其写为board = [["O"]*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)

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

【问题讨论】:

  • 请注意,列表在 Python 中从 0 开始索引。因此board[0][0] 将返回第 1 行第 1 列。
  • 顺便说一句,这不是 2.x 特有的:它一直以这种方式工作,而且几乎肯定会一直以这种方式工作。

标签: python list python-2.7 append python-2.x


【解决方案1】:

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

board[0] is board[1]

如果您确实想要一个简短的版本来制作不同的新列表,那么这个版本也可以正常工作。

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

【讨论】:

  • 使用id 函数可能也很有趣:print id(board[0]print id(board[1])
【解决方案2】:

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

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

是的,["O"] * 5 会生成一个包含 5 个事物的列表,每个事物都是相同的 "O"。但是,这实际上并不相关。没有有意义的“不同的"O"”之类的东西,因为你不能改变"O" - 无论你对一个命名的变量做什么,"O""O" 仍然是"O".

【讨论】:

    【解决方案3】:

    您的第一个表达式是创建一个指向单个列表对象的指针列表。因此,当您更新一个元素时,它会随处更改。

    【讨论】:

      猜你喜欢
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      • 2016-07-21
      • 1970-01-01
      • 2019-08-16
      • 1970-01-01
      • 2018-08-03
      • 1970-01-01
      相关资源
      最近更新 更多