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