如果我有这个Python代码:
foo = [3, 5, 9]
bar = foo
bar.append(9)
print(foo)
返回
[3, 5, 9, 9]
这肯定意味着当我将9
添加到bar
时,它也会影响foo
。如何使变量bar
等于foo
,但是当我修改bar
时,它不会影响foo
?
答案 0 :(得分:5)
您正在更改可变值,因此您需要制作一个明确的副本:
bar = list(foo)
或
bar = foo[:]
在Python中分配名称时,您只需将引用存储到该值中。如果不创建列表副本,foo
和bar
都会引用相同的列表。
对于非可变值,这不是问题;你将一个字符串的引用替换为一个字符串,而不是指向一个不同的值。
但是列表(以及dict
和set
以及大多数类的实例)都是可变的。您没有更改foo
,您更改了值foo
引用。你做了foo.append(9)
,Python认为:
foo
引用的值。.append
。这将返回列表实例上的方法。9
。这改变了清单。 Python名称本身只不过是标签,指向实际值。您可以将值视为气球,将名称视为小纸标签,分配是将标签绑定到气球的行为。 bar = foo
创建了第二个纸质标签,该标签与完全相同的气球相关联。
请参阅此older answer of mine我将气球比喻推到一起。
答案 1 :(得分:2)
你制作副本:
bar = foo[:] #copy of foo
bar.append(9)
这与python如何处理赋值有关。分配说“将对象放在右侧并将其存储在本地命名空间左侧的名称下”。所以,在你的情况下,你有foo和bar引用同一个对象,这就是为什么追加到另一个也会影响另一个对象。
当使用通常操作对象的运算符(例如+=
)时,对于不可变对象,事情会变得更有趣。例如,请参阅my answer here以及更多解释。
答案 2 :(得分:2)
在删除对原稿的所有引用(因此无法编辑原件)时创建原件的副本时,使用深层复制。
http://docs.python.org/2/library/copy.html
import copy
bar = copy.deepcopy(foo)
答案 3 :(得分:2)
使用deepcopy
:
>>> from copy import deepcopy
>>> foo = [3, 5, 9]
>>> bar = deepcopy(foo)
>>> bar.append(9)
>>> print(foo)
[3, 5, 9]
>>> print bar
[3, 5, 9, 9]