在python中初始化矩阵

时间:2011-06-15 10:13:52

标签: python list

  

可能重复:
  Python list problem

我尝试在python中初始化一个矩阵。 首先我这样做了:

>>> M=[[0]*4]*4

但这是我的问题,当我改变第一个时,每一行都在改变:

>>> M
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> M[1][1]=1
>>> M
[[0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]]

所以我这样做了:

>>> M= [ [ 0 for i in range(4) ] for j in range(4) ]

并且工作正常:

>>> M
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> M[1][1]=1
>>> M
[[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

我的问题是:

这两个表达的真正含义是什么?为什么第一个这样做?

先谢谢你的帮助。

3 个答案:

答案 0 :(得分:3)

当你将这些列表相乘时,Python会通过引用复制它们,而不是创建全新的对象。

一个简单的例子可能有所帮助,显示通过引用复制会发生什么:

>>> pie = ['apple', 'cherry', 'pecan']
>>> pie_copy = pie
>>> pie_copy[0] = 'banana'
>>> pie
['banana', 'cherry', 'pecan']
>>> pie is pie_copy
True
>>> new_pie = ['banana', 'cherry', 'pecan']
>>> pie is new_pie
False

与pie_copy和pie指向同一列表的方式相同,在通过相乘构建列表时,所有副本都指向同一列表。

在使用range()和列表推导的第二个代码段中,您没有使用单个列表并将其复制多次;理解中的每次迭代都会创建一个新列表,因此您不会受到引用问题的同一副本的影响。

答案 1 :(得分:2)

因为M=[[0]*4]*4 您可以在对象上创建链接。

类似
>>> a = [0, 0, 0]
>>> b = [a,a,a]
>>> b
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[1] = 1
>>> b
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
>>>

UPD 链接我的意思是引用,抱歉,如果有点混乱

答案 2 :(得分:1)

a是一些python对象。然后[a] * 4相当于[a,a,a,a]。这意味着取决于a是否可变。数字,字符串和元组不是,所以如果a是这些类型的对象之一(在您的示例中为0),那么您将获得4个可独立更改的副本。列表,字典和集合是可变的,在这种情况下,您只需获得对同一对象的4个引用,在您的情况下,列表为[0] * 4。利用这些知识,你会发现你可以做到这一点:

M = [[0] * 4 for i in range(4)]

得到你想要的东西。