copy --- 浅层 (shallow) 和深层 (deep) 复制操作

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']])

你可能感兴趣的:(copy --- 浅层 (shallow) 和深层 (deep) 复制操作)