copy --- 浅层 (shallow) 和深层 (deep) 复制操作
发布网友
发布时间:2022-12-05 19:38
我来回答
共1个回答
热心网友
时间:2024-11-29 22:29
copy --- 浅层 (shallow) 和深层 (deep) 复制操作
Python 中赋值语句不复制对象,而是在目标和对象之间创建绑定 (bindings) 关系。对于自身可变或者包含可变项的集合对象,开发者有时会需要生成其副本用于改变操作,进而避免改变原对象。
直接赋值: 其实就是对象的引用(别名)。
浅拷贝(copy): 拷贝父对象,不会拷贝对象的内部的子对象。
深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。
copy模块提供了通用的浅层复制和深层复制操作的方法。
copy.copy( x )返回 x 的浅层复制。
copy.deepcopy( x [, memo ])返回 x 的深层复制。
exception copy.error针对模块特定错误引发。
浅层复制和深层复制之间的区别仅与复合对象 (即包含其他对象的对象,如列表或类的实例) 相关:
一个 浅层复制 会构造一个新的复合对象,然后(在可能的范围内)将原对象中找到的 引用 插入其中。
一个 深层复制 会构造一个新的复合对象,然后递归地将原始对象中所找到的对象的 副本 插入。
深层复制操作通常存在浅层复制操作不存在的两个问题:
递归对象 (直接或间接包含对自身引用的复合对象) 可能会导致递归循环。
由于深层复制会复制所有内容,因此可能会过多复制(例如本应该在副本之间共享的数据)。
deepcopy()函数避免通过以下方法这些问题:
保留在当前复制过程中已复制的对象的 "备忘录" (memo) 字典;
允许用户定义的类重载复制操作或复制的组件集合。
该模块不复制模块、方法、栈追踪(stack trace)、栈帧(stack frame)、文件、套接字、窗口、数组以及任何类似的类型。它通过不改变地返回原始对象来(浅层或深层地)“复制”函数和类。
制作字典的浅层复制可以使用 dict.copy() 方法,而制作列表的浅层复制可以通过复制整个列表的切片完成,例如,copied_list = original_list[:]。
类可以使用与控制序列化(pickling)操作相同的接口来控制复制操作,关于这些方法的描述信息请参考 pickle 模块。实际上,copy模块使用的正是从 copyreg 模块中注册的 pickle 函数。
想要给一个类定义它自己的拷贝操作实现,可以通过定义特殊方法__copy__()和__deepcopy__()。 调用前者以实现浅层拷贝操作,该方法不用传入额外参数。
调用后者以实现深层拷贝操作——它应传入一个参数即memo字典。 如果__deepcopy__()实现需要创建一个组件的深层拷贝,它应当调用 deepcopy() 函数并以该组件作为第一个参数,而将 memo 字典作为第二个参数。
下面我们通过例子来深入理解
字典浅拷贝实例
#浅拷贝可以导入copy也可以不导入>>>a = {1: [1,2,3]}>>> b = a.copy()>>> a, b({1: [1,2,3]}, {1: [1,2,3]})>>> a[1].append(4)>>> a, b({1: [1,2,3,4]}, {1: [1,2,3,4]})
字典深拷贝实例
#深度拷贝必须导入copy模块>>>importcopy>>> c = copy.deepcopy(a)>>> a, c({1: [1,2,3,4]}, {1: [1,2,3,4]})>>> a[1].append(5)>>> a, c({1: [1,2,3,4,5]}, {1: [1,2,3,4]})
解析
1、 b = a:: 赋值引用,a 和 b 都指向同一个对象。
2、b = a.copy(): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。
b = copy.deepcopy(a): 深度拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。
更多实例(列表)
以下实例是使用 copy 模块的 copy.copy( 浅拷贝 )和(copy.deepcopy ):
#!/usr/bin/python# -*-coding:utf-8 -*-importcopya = [1,2,3,4, ['a','b']]#原始对象b = a#赋值,传对象的引用c = copy.copy(a)#对象拷贝,浅拷贝d = copy.deepcopy(a)#对象拷贝,深拷贝a.append(5)#修改对象aa[4].append('c')#修改对象a中的['a', 'b']列表对象print('a = ', a )print('b = ', b )print('c = ', c )print('d = ', d )
以上实例执行输出结果为:
('a = ', [1,2,3,4, ['a','b','c'],5])('b = ', [1,2,3,4, ['a','b','c'],5])('c = ', [1,2,3,4, ['a','b','c']])('d = ', [1,2,3,4, ['a','b']])