Python对象混淆:a=b,修改b,a也改变!
我一直以为我懂Python,直到今晚。我想知道,像这样做的正确方法是什么?这是我的代码:
a = ["one", "two", "three"]
b = a # here I want a complete copy that when b is changed, has absolutely no effect on a
b.append["four"]
print a # a now has "four" in it
简单来说,我想知道,怎么才能正确地复制一个列表或字典,这样当我改变b的时候,a就不会跟着改变?
3 个回答
1
复制一个对象的正确方法是
from copy import copy
a = [1, 2, 3]
b = copy(a)
这很简单。对于列表,有一些快捷方式:
a = [1, 2, 3]
b = a[:]
如果你想要连列表里面的对象也一起复制,可以使用deepcopy()。
1
这里有三种方法可以复制列表 a
:
第一种方法是使用切片语法:
copy_of_a = a[:]
第二种方法是使用列表构造函数:
copy_of_a = list(a)
第三种方法是使用复制模块:
from copy import copy
copy_of_a = copy(a)
这些都是浅拷贝,对于你的问题来说已经足够了。如果想了解浅拷贝和深拷贝之间的区别,可以查看复制模块的文档。
18
你遇到的这个问题其实是关于“引用”的概念。在Python中,所有的对象都有一个引用。当你把一个对象同时赋值给两个名字,比如a
和b
时,这意味着a
和b
都指向同一个对象。
>>> a = range(3)
>>> b = a # same object
>>> b.append(3)
>>> a, b # same contents
([0, 1, 2, 3], [0, 1, 2, 3])
对于列表来说,你可以通过b = a[:]
来创建一个新的列表b
,这个新列表是另一个列表a
的一个“拷贝”。
>>> a = range(3)
>>> b = a[:] # make b a new copy of a
>>> b.append(3)
>>> a, b # a is left unchanged
([0, 1, 2], [0, 1, 2, 3])
如果你想要一个更通用的方法来处理任何对象,可以使用copy模块。浅拷贝会复制你正在拷贝的对象中存储的引用,而深拷贝则会递归地为所有对象创建新的拷贝。
>>> a = [range(2), range(3)]
>>> b = copy.copy(a) # shallow copy of a, equivalent to a[:]
>>> b[0] = range(4)
>>> a, b # setting an element of b leaves a unchanged
([[0, 1], [0, 1, 2]], [[0, 1, 2, 3], [0, 1, 2]])
>>> b[1].append(3)
>>> a, b # modifying an element of b modifies the element in a
([[0, 1], [0, 1, 2, 3]], [[0, 1, 2, 3], [0, 1, 2, 3]])
>>> a = [range(2), range(3)]
>>> b = copy.deepcopy(a) # deep recursive copy of a
>>> b[1].append(3)
>>> a, b # modifying anything in b leaves a unchanged
([[0, 1], [0, 1, 2]], [[0, 1], [0, 1, 2, 3]])