变量赋值与修改(在Python中)
当我运行这个脚本(Python v2.6)时:
a = [1,2]
b = a
a.append(3)
print a
>>>> [1,2,3]
print b
>>>> [1,2,3]
我本来期待 print b
会输出 [1,2]
。为什么当我只改变了 a 的时候,b 也发生了变化?b 是不是和 a 永远绑在一起了?如果是这样的话,我能让它们独立开来吗?怎么做?
6 个回答
4
简单来说,就是指针。
当你输入 b = a
时,其实是在让 b
指向和 a
一样的数组。如果你想让它们分开,就得新建一个数组,并把元素复制过去。在这种情况下,像 b = [n for n in a]
这样的写法就可以了。如果你需要进行更复杂的操作,可以去看看 http://docs.python.org/library/copy.html。
13
在Python中,对象是通过引用来存储的,也就是说,你并不是把a
的值赋给b
,而是把a
所指向的对象的地址给了b
。
如果你想模拟值的赋值,可以像这样复制一个对象:
import copy
b = copy.copy(a)
# now the code works as "expected"
需要注意的是,这样做会影响性能。
对于数组,有一种特殊的方法可以利用切片来实现:
b = a[:]
# code also works as expected here
更新– 除此之外,对于某些对象,你可以使用构造函数,这包括列表:
b = list(a)
63
在Python中,内存管理是通过一个私有的堆内存区域来处理的,这里存放着所有的Python对象和数据结构。
Python的运行时只处理对象的引用(这些对象都在堆内存中):在Python的栈中,存放的总是指向其他地方的值的引用。
>>> a = [1, 2]
>>> b = a
>>> a.append(3)
在这里,我们可以清楚地看到变量 b
和 a
绑定到了同一个对象上。
你可以使用 is
操作符来检查两个对象是否是同一个物理对象,也就是说,它们在内存中的地址是否相同。你也可以使用 id()
函数来进行这个测试。
>>> a is b
>>> True
>>> id(a) == id(b)
>>> True
所以,在这种情况下,你必须明确要求复制。一旦你这样做了,两个不同的列表对象之间就没有任何连接了。
>>> b = list(a)
>>> a is b
>>> False