【问题标题】:Two-dimensional list wrongly assigning values in python二维列表在python中错误地赋值
【发布时间】:2013-09-11 03:41:52
【问题描述】:
class Board:

    def __init__(self):
        self.board = self.createBoard()

    def createBoard(self):
        line = []
        for i in range(7):
            line.append(' ')
        board = []
        for i in range(7):
            board.append(line)
        return board

    def showBoard(self):
        line = "| "
        for x in range(len(self.board)):
            for y in range(len(self.board)):
                line += self.board[x][y] + " | "
            print("-" * 29)
            print(line)
            line = "| "
        print("-" * 29)

if __name__ == '__main__':
    board = Board()
    board.showBoard()
    board.board[1][1] = "O"
    board.showBoard()

当我遇到这个非常奇怪的问题时,我正在开发一个 connect-4 python 控制台演示/游戏。

上面代码的输出如下:

-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------

奇怪的是,我从未将O 分配给所有这些位置,我只将它分配给位置 [1][1]。

我预计输出是:

-----------------------------
|   |   |   |   |   |   |   | 
-----------------------------
|   | O |   |   |   |   |   | 
-----------------------------
|   |   |   |   |   |   |   | 
-----------------------------
|   |   |   |   |   |   |   | 
-----------------------------
|   |   |   |   |   |   |   | 
-----------------------------
|   |   |   |   |   |   |   | 
-----------------------------
|   |   |   |   |   |   |   | 
-----------------------------

我极有可能遗漏了一些明显而小的东西,但我一直在寻找和尝试一个多小时,但我真的找不到问题。

这不像我的 board.board 列表比任何其他二维列表都更奇怪。

[[' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' ']]

(这是我print(board.board)时得到的)

将其复制并粘贴到 IDLE 中,我得到以下信息:

>>> a = [[' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' ']]
>>> a[1][1] = "O"
[[' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', 'O', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' ']]

这让我得到了正确的董事会价值。

我的代码中有什么明显错误以至于我遗漏了它?我敢肯定,当你们中的任何人找到一个我会羞愧地摇头的答案时,很可能就是那么糟糕。

够自卑了,那为什么我的代码board.board[1][1] = "O" 将值“O”分配给board.board 中的每一行?

将第一个 1 更改为 0-6 之间的任何其他数字也不会改变任何内容。都是一样的。

【问题讨论】:

  • 我确信这是 100 个其他问题的重复,但不幸的是,很难找出好的搜索词来找到它,所以很难责怪任何人重复这个问题......右边的相关问题肯定是相关的,但似乎没有一个是重复的。

标签: python multidimensional-array assign


【解决方案1】:

这在常见问题解答中进行了解释,How do I create a multidimensional list?

问题出在这部分代码中:

board = []
for i in range(7):
    board.append(line)

您正在创建一个包含 7 个对同一列表 line 的引用的列表。所以,当你修改一个时,其他的都会改变,因为它们是同一个列表。

解决方案是创建 7 个单独的列表,如下所示:

def createBoard(self):
    board = []
    for i in range(7):
        line = []
        for i in range(7):
            line.append(' ')
        board.append(line)
    return board

或者,更简单地说,制作原始列表的单独副本:

def createBoard(self):
    line = []
    for i in range(7):
        line.append(' ')
    board = []
    for i in range(7):
        board.append(line[:])
    return board

虽然我们正在这样做,但您可以通过使用列表推导来极大地简化它:

def createBoard(self):
    return [[' ' for j in range(7)] for i in range(7)]

或者,正如常见问题解答所建议的,您最好使用更智能的多维数组对象,例如 numpy 或 pandas 提供的对象:

def createBoard(self):
    return np.tile(' ', (7, 7))

缺点是您需要安装 numpy,因为标准库中没有任何东西可以像这样工作。但好处是你有强大的工具来处理数组——a[1, 1] 并不比a[1][1] 简单得多,但是a[:,1] 访问第二列却比[row[1] for row in a] 简单得多。

【讨论】:

  • 和我想的一样,小而简单。感谢您的快速回答,并因为参考了常见问题解答而被选为最佳答案。
【解决方案2】:

这是 python 使用引用的问题。 CreateBoard第二部分

    for i in range(7):
        board.append(line)

将 7 个对同一个列表的引用放在外部列表中。所以你有一个相同列表的 7 个副本的列表。编辑其中一个子列表中的值实际上会更新所有子列表,因为它们引用相同的内存。

一种选择是使用 copy.deepcopy,或者为每一行显式创建一个新列表

import copy  # at the top of the file
for i in range( 7 ):
    board.append( copy.deepcopy( line ) )

for i in range( 7 ):
    board.append( list(' ' * 7) )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-14
    • 2018-09-22
    • 2021-12-31
    • 1970-01-01
    • 2017-06-25
    • 2012-12-13
    • 2021-01-29
    • 1970-01-01
    相关资源
    最近更新 更多