Python列表初始化(通过ref问题)

Eri*_*ver 0 python arrays list

我有一些简单的代码,使用方形布尔矩阵表示图形,其中行/列是节点,而true表示两个节点之间的无向链接.我正在使用False值初始化此矩阵,然后将值设置为True,其中存在链接.

我相信我初始化列表的方式是导致给定行中的每个单元格引用单个bool实例.结果是,如果我将任何单元格设置为True,则该行中的所有其他单元格也将变为True.

我应该如何初始化我的方形矩阵,以便所有值都是假的,但没有一个是通过引用与其他单元格共享的?

import sys

class Graph(object):
    def __init__(self, nodeCount, links):
        self.matrix = [[False] * nodeCount] * nodeCount
        for l in links:
            self.matrix[l[0]][l[1]] = True

    def __str__(self):
        s = "  "
        for i in range(len(self.matrix)):
            s += str(i) + " "
        s += "\n"
        for r in range(len(self.matrix)):
            s += str(r) + " "
            for c in range(len(self.matrix)):
                s += str(self.matrix[c][r])[0] + " "
            s += "\n"
        return s

g = Graph(5, [(2,3)])
print g
Run Code Online (Sandbox Code Playgroud)

另外,在GIST上

Dev*_*rre 5

实际上,你有点误解了这个问题.您认为布尔引用是共享的(这是真的,但并不重要 - 布尔值是不可变的,因此共享对同一对象的引用并不意味着太多).发生的事情是列表引用是共享的,这引起了你的麻烦.让我演示给你看:

你的代码是这样的

[[False] * nodeCount] * nodeCount
Run Code Online (Sandbox Code Playgroud)

会发生的是您获得nodeCountnodeCount引用False 的单个列表的引用.将一个序列乘以整数给出一个带有重复引用的序列 - 它们不是副本,它们是别名.

>>> x = [False] * 3
>>> y = [x] * 3
>>> y[0] is y[1]
True
>> # your problem
>>> y[0][0] = True
>>> y[1]
[True, False, False]
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,这意味着您无法更改单个行,因为所有行都是相同的列,并且更改一行会更改所有行.

要解决此问题,请为每行创建新列表:

[[False]*nodeCount for _ in xrange(nodeCount)]
Run Code Online (Sandbox Code Playgroud)

例:

>>> y = [[False]*3 for _ in xrange(3)]
>>> y[0] is y[1]
False
>>> y[0][0] = True
>>> y[1]
[False, False, False]
Run Code Online (Sandbox Code Playgroud)