4

我是编程新手,我有这个无法解决的基本问题。我尽可能地简化了它。在这个简化版本中,我正在遍历一个空列表。我只想将索引存储在“对称矩阵”中:

n = 2
B = [[None] * n] * n
print B, "\n"
for i in range(n):
    for j in range(n):
        B[i][j] = [i, j]
        print B

最初,列表如下所示:

[[None, None], [None, None]] 

循环低谷后,我希望打印输出为:

[[[0, 0], None], [None, None]]
[[[0, 0], [0, 1]], [None, None]]
[[[1, 0], [0, 1]], [[1, 0], None]]
[[[1, 0], [1, 1]], [[1, 0], [1, 1]]]

相反,我得到了这个:

[[[0, 0], None], [[0, 0], None]]
[[[0, 0], [0, 1]], [[0, 0], [0, 1]]]
[[[1, 0], [0, 1]], [[1, 0], [0, 1]]]
[[[1, 0], [1, 1]], [[1, 0], [1, 1]]]

我错过了什么?感谢您的帮助...

4

4 回答 4

3

您的初始化创建了对同一列表的两个引用:

n=2
B=[[None]*n]*n
for x in B:
     print id(x)

输出:

4534759576
4534759576
于 2013-10-18T13:01:37.890 回答
3

您需要的是子列表的“新”实例,而不是当前定义B的方式:n

B = [[None] * n for _ in range(n)]

这等效于但更短并且(对于 Pythonista 而言)比以下内容更具可读性:

B = []
for _ in range(n):
    B.append([None] * n)

这是因为 Python 中的列表不是值而是对象。即默认情况下不会复制它们。例如:

>>> a = []
>>> b = [a, a]  # list of 2 items, both pointing to the same list instance
>>> b[0].append(1)  # b[0] refers to the same list instance also referenced by a
>>> print b
[[1], [1]]

然而:

>>> b = [[], []]  # list of 2 distinct sublists
>>> b[0].append(1)
>>> print b
[[1], []]

如果你将这些知识应用到

B = [[None] * n] * n

你会看到构造中有一个错误——你正在创建一个包含另一个值列表的列表n None;然后,您将“升迁”列表以包含n此类列表;但是,将使用相同的列表实例,就像上面更简单的示例一样。

PS更准确地说,Python 中的一切都是对象而不是值,除非对象是不可变的,例如ints 和floats 和strs 等,就好像它们是值并且总是被复制——这是因为如果一个对象是不可变的,您不妨假装对它的新引用是它的新副本,因为它看起来相同且无法修改。

于 2013-10-18T13:09:49.380 回答
1

这是你可以做的,你想要什么:

    n=2
    B = [[None for i in range(n)] for i in range(n)]
    print B, "\n"
    for i in range(n):
        for j in range(n):
        B[i][j] = [i, j]
        print B
于 2013-10-18T13:10:54.137 回答
1

了解这里发生的事情的关键是了解您在使用该[[None]*n]*n方法时正在创建具有共享引用的列表。看看你的代码做了什么的可视化,它应该让事情更清楚。这篇博文还解释了名称和值在 Python 中是如何工作的。

于 2013-10-18T13:15:12.737 回答