我试图做浅副本,但它对我不起作用。
import copy
a = [1,2,3,4]
b = copy.copy(a)
现在a
和b
都具有相同的值[1,2,3,4]。但是,如果我附加b.append(1)
,则不会反映在A。
b.append(1)
print(b)
[1,2,3,4,1]
但是在
中print(a)
[1,2,3,4]
任何人都可以解释吗?
首先:您得到的是预期行为。"浅"副本表示您创建对象的新副本,因此添加到列表b
显然不会影响列表a
。
我只想了解deepcopy和浅副本之间的区别。因为浅拷贝和底部的行为以相同的方式
在您的示例中,您正在执行包含不变对象(整数(的可变容器(列表(的浅副本,因此结果确实相同。要找出必须使用包含可变对象的列表的浅副本和深副本之间的区别 - 例如:
>>> import copy
>>> a = [{"name":"a"}, {"name":"b"}]
>>> b = copy.copy(a)
>>> a[0]["age"] = 42
>>> a
[{'age': 42, 'name': 'a'}, {'name': 'b'}]
>>> b
[{'age': 42, 'name': 'a'}, {'name': 'b'}]
>>> a.append({"bar":"baaz"})
>>> a
[{'age': 42, 'name': 'a'}, {'name': 'b'}, {'bar': 'baaz'}]
>>> b
[{'age': 42, 'name': 'a'}, {'name': 'b'}]
>>> id(a)
139833628392264
>>> id(b)
139833599561240
>>> [id(x) for x in a]
[139833628091568, 139833599520392, 139833599544128]
>>> [id(x) for x in b]
[139833628091568, 139833599520392]
如您所见,a
和b
是不同的对象 - 它们具有不同的ID,并且添加到一个对象并不会添加到另一个ID-但它们(最初至少(共享相同的对象(在复制a[0]
和a[1]
指向与b[0]
和b[1]
的对象相同的对象。
现在,如果您进行了深层副本:
>>> c = copy.deepcopy(a)
>>> c
[{'age': 42, 'name': 'a'}, {'name': 'b'}, {'bar': 'baaz'}]
>>> [id(x) for x in c]
[139833599544408, 139833599594576, 139833599596256]
>>> c[0]["age"] = 84
>>> c
[{'age': 84, 'name': 'a'}, {'name': 'b'}, {'bar': 'baaz'}]
>>> a
[{'age': 42, 'name': 'a'}, {'name': 'b'}, {'bar': 'baaz'}]
>>> b
[{'age': 42, 'name': 'a'}, {'name': 'b'}]
>>>
您可以看到c
元素本身是a
元素的副本(不同的对象(。
如果您真的想了解名称,对象和参考在Python中的工作方式,则Ned Batchelder的文章是一个很好的参考。
这正是浅副本所做的。您的列表元素将相同,但列表本身将是一个不同的对象。
如果您想对同一列表有另一个引用,请这样做:
b = a
副本使a
和b
不同的列表对象存储相同的项目:
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import copy
>>> a = [1,2,3,4]
>>> b = copy.copy(a)
>>> a is b
False
浅副本确实意味着列表内部的项目相同,例如:
>>> a = [object(), "foo", "bar"]
>>> b = copy.copy(a)
>>> a[0] is b[0]
True
>>> a[1] is b[1]
True
如果您想要的只是参考,则可以分配:
>>> a = [1,2,3,4]
>>> b = a
>>> a is b
True
>>> b.append(1)
>>> b
[1, 2, 3, 4, 1]
>>> a
[1, 2, 3, 4, 1]