谁能解释一下这里发生了什么?我了解 pythonint
是按值分配的(而不是按引用分配的)。
>>> alist = [1,2,3]
>>> a = [[0]*3]*4
>>> a[0][0] = len(alist)
>>> alist.append(1)
>>> a[1][0] = len(alist)
>>> a[0][0]a
4
>>>
当您使用符号创建列表时*
,您正在重复相同的元素。不是元素的副本,而是相同的对象。
当您重复的对象是不可变的(例如整数)时,您不会注意到。
当对象是可变的(例如列表)时,您会得到重复的相同列表。如果您对一个列表进行更改,那么您将对所有列表进行更改。
在您的情况下,您对 element 进行了更改[1]
,它反映在 element 中[0]
。
问题是您的外部列表包含相同内部列表值的多个副本。您可以这样判断:
a = [[0]*3]*4
print(a[0] is a[1]) # prints True
如果你想要一个二维的零列表,我建议对外部使用列表推导,以便获得单独的内部列表实例:
a = [[0]*3 for _ in range(4)]
print(a[0] is a[1]) # prints False
a[0][0]=1
print(a[1][0]) # prints 0
这可能会有所帮助(只是在每一行转储list
和的值):a
#With some commentary
>>> alist = [1,2,3] #Created a list with 3 elements
>>> alist
[1, 2, 3]
>>> a = [[0]*3]*4 #Created a list with 3 copies of one element and then copied it 4 times
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0] = len(alist) #Set the 0th element of the 0th copy to 3
>>> a #Now you can see where that value was copied
[[3, 0, 0], [3, 0, 0], [3, 0, 0], [3, 0, 0]]
#The rest is just a permutation of that first 'bug'
>>> alist.append(1)
>>> alist
[1, 2, 3, 1]
>>> a[1][0] = len(alist)
>>> a
[[4, 0, 0], [4, 0, 0], [4, 0, 0], [4, 0, 0]]
>>> a[0][0]
4
关于这段代码的一个不直观的事情可能是它[0]*3
似乎做了你所期望的,而[[0]*3]*4
没有做到。为此,我只能猜测(还不是 Python 专家)单个长度的 int 列表是以一种看起来很直观的方式处理的,而列表列表则回到了复制方法。
没问题。[[0]*3]*4
创建了一个包含 3 个元素列表的 4 个副本的列表。a[0]、a[1]、a[2] 和 a[3] 都指向同一个列表。
>>> a=[[0]*3]*4
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]='hello'
>>> a
[['hello', 0, 0], ['hello', 0, 0], ['hello', 0, 0], ['hello', 0, 0]]
>>> for mylist in a:
... print id(a)
...
42701168
42701168
42701168
42701168
>>>