说我有一个清单:
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]
答案 0 :(得分:3)
问题是a
和L[0]
是对不可变对象的引用,因此更改其中任何一个都不会影响其他引用:
>>> L = [1, 2, [3]]
>>> a = L[0]
>>> a = a + 1
a
现在指向一个新对象,而L[0]
仍然指向同一个对象。
>>> a, L[0]
(2, 1)
现在,在这种情况下,b
和L[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]
在这种情况下,a
和L[0]
都指向同一个对象。
答案 3 :(得分:0)
将作业更改为:
a = L
然后将L更改为:
L[0] += 1
你会看到一个也发生了变化。这是参考魔术。