对于在python中将列表项分配给变量而感到困惑

时间:2013-09-25 06:26:19

标签: python list variables reference

说我有一个清单:

L = [1,2,3]

我已将L[0]分配给变量a

a = L[0]

然后,如果我更改a,则不会影响L

a = a + 1
print L # [1,2,3] not affected

为什么会这样?是不是python通过引用传递一切?我认为a指向L[0]

4 个答案:

答案 0 :(得分:3)

问题是aL[0]是对不可变对象的引用,因此更改其中任何一个都不会影响其他引用:

>>> L = [1, 2, [3]]
>>> a = L[0]
>>> a = a + 1

a现在指向一个新对象,而L[0]仍然指向同一个对象。

>>> a, L[0]   
(2, 1)

现在,在这种情况下,bL[2]是对可变对象(list)的引用,对它们的任何就地操作都会影响所有引用:

>>> b = L[2]
>>> b.append(4)  #list.append is an in-place operation
>>> b, L[2]
([3, 4], [3, 4])

>>> b = b + [5]  #mutable object, but not an in-place operation 
>>> b            #b is assigned to new list object
[3, 4, 5]
>>> L[2]         #L[2] is unchanged
[3, 4]

答案 1 :(得分:2)

L[0]是一个名称,当您创建列表L时,您将一个对象分配给该名称,即整数1. a也是一个名称,当您指定时与a = L[0]中一样,您使a指向L[0]指向的同一对象。

但是当您稍后执行a = a + 1时,这是另一项任务。您没有修改a指向的对象 - =符号无法执行此操作。您正在创建一个新对象,即整数2,并将其分配给a

所以最后,你在内存中有两个对象;一个由L[0]引用,另一个由a引用。

整数是不可变的,这意味着在这个例子中没有可能的方法来改变对象的属性;然而,在这个例子中,这并不是很突出,因为即使对象是可变的,也不会改变你正在进行任务的事实(使用=符号)。在有问题的对象是可变的情况下,理论上可以在L[0]a引用对象时更改对象的属性,而不是使用=进行任何其他赋值就像你在做。此时,无论您使用哪个名称检查对象,都会看到属性发生变化。

答案 2 :(得分:1)

由于您的L[0]immutable,因此更改a不会影响L[0]的值。当您更改a时,会创建对象,a开始指向它。

如果L[0]属于可变类型,请查看会发生什么:

>>> L = [[1],2,3]
>>> a = L[0]
>>> a.append(2)
>>> L
[[1, 2], 2, 3]

在这种情况下,aL[0]都指向同一个对象。

另请参阅Raymond Hettinger's answer中的relevant thread

答案 3 :(得分:0)

将作业更改为:

a = L

然后将L更改为:

L[0] += 1

你会看到一个也发生了变化。这是参考魔术。