当我运行此脚本时(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]
。当我所做的一切都是改变时,为什么b会改变?是b永久绑在一个?如果是这样,我可以让它们独立吗?怎么样?
答案 0 :(得分:48)
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
答案 1 :(得分:13)
Python中的对象是通过引用存储的 - 您没有将a
的值赋给b
,而是指向a
指向的对象的指针。
要按值模拟分配,您可以制作如下副本:
import copy
b = copy.copy(a)
# now the code works as "expected"
请注意这有性能劣势。
对于数组,有一种依赖切片的特殊方法:
b = a[:]
# code also works as expected here
更新 - 除此之外,对于某些对象,您可以使用构造函数 - 这包括列表:
b = list(a)
答案 2 :(得分:4)
简短回答 - 指针。
当您输入b = a
时,它会设置b
以查看a
查看的相同数组。您必须创建一个包含元素副本的新数组以将它们分开。在这种情况下,像b = [n for n in a]
这样的东西可以正常工作。对于更复杂的操作,您可能需要查看http://docs.python.org/library/copy.html。
答案 3 :(得分:4)
您可能需要查看this链接。您遇到的问题是a
和b
都指向相同的内存位置,因此更改另一个会更改另一个内存位置。相反,你想做这样的事情:
a = [1,2]
b = list(a)
答案 4 :(得分:3)
a
是指向列表[1,2]
的指针。
执行作业b = a
时,b的值是列表[1,2]
的地址。
因此,当您执行a.append(3)
时实际上并未更改a
,您正在更改a
指向的列表。由于a
和b
都指向同一个列表,因此当您修改另一个列表时,它们似乎都会发生变化。
答案 5 :(得分:2)
如果您只是想将列表a的内容复制到b,而不是将b指向a:
b = a[:]
使用切片运算符会将列表的内容复制到b中,以便您的示例变为:
a = [1,2]
b = a[:]
a.append(3)
print a
>>>> [1,2,3]
print b
>>>> [1,2]