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

时间:2010-07-10 06:35:05

标签: python arrays list

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

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

我应该如何初始化我的方形矩阵,以便所有值都为false但是没有与其他单元格共享?

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

此外,在GIST

2 个答案:

答案 0 :(得分:5)

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

您的代码就是这个

[[False] * nodeCount] * nodeCount

当您使用nodeCount引用False的单个列表获得nodeCount个引用时,会发生什么。将一个序列乘以整数给出一个带有重复引用的序列 - 它们不是副本,而是别名。

>>> x = [False] * 3
>>> y = [x] * 3
>>> y[0] is y[1]
True
>> # your problem
>>> y[0][0] = True
>>> y[1]
[True, False, False]

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

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

[[False]*nodeCount for _ in xrange(nodeCount)]

示例:

>>> y = [[False]*3 for _ in xrange(3)]
>>> y[0] is y[1]
False
>>> y[0][0] = True
>>> y[1]
[False, False, False]

答案 1 :(得分:1)

self.matrix = [[False] * nodeCount] * nodeCount

应该是

self.matrix = [[False] * nodeCount for _ in  range(nodeCount)]