二维列表在python中错误地赋值

时间:2013-09-06 23:15:51

标签: python multidimensional-array assign

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中的任何其他数字也不会改变任何内容。它完全一样。

2 个答案:

答案 0 :(得分:6)

常见问题解答在How do I create a multidimensional list

下进行了解释

问题在于代码的这一部分:

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

您正在创建一个列表,其中包含对同一列表line的7个引用。因此,当您修改其中一个时,其他所有内容都会更改,因为它们是相同的列表。

解决方案是创建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]比{{1}简单得多}}

答案 1 :(得分:0)

这是使用引用的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 ) )

OR

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