可能重复:
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]]
我的问题是:
这两个表达的真正含义是什么?为什么第一个这样做?
先谢谢你的帮助。
答案 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)]
得到你想要的东西。