2

谁能解释一下这里发生了什么?我了解 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
>>> 
4

4 回答 4

4

当您使用符号创建列表时*,您正在重复相同的元素。不是元素的副本,而是相同的对象。

当您重复的对象是不可变的(例如整数)时,您不会注意到。

当对象是可变的(例如列表)时,您会得到重复的相同列表。如果您对一个列表进行更改,那么您将对所有列表进行更改。

在您的情况下,您对 element 进行了更改[1],它反映在 element 中[0]

于 2013-03-25T22:36:42.390 回答
3

问题是您的外部列表包含相同内部列表值的多个副本。您可以这样判断:

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
于 2013-03-25T22:35:39.453 回答
2

这可能会有所帮助(只是在每一行转储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 列表是以一种看起来很直观的方式处理的,而列表列表则回到了复制方法。

于 2013-03-25T22:29:58.107 回答
0

没问题。[[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
>>>
于 2013-03-25T22:35:27.180 回答