copy — 浅拷贝和深拷贝操作

源代码: Lib/copy.py


Python 中的赋值语句不会复制对象,而是创建目标和对象之间的绑定。对于可变或包含可变项的集合,有时需要复制,以便可以更改一个副本而不更改另一个副本。此模块提供通用的浅拷贝和深拷贝操作(如下所述)。

接口摘要

copy.copy(x)

返回 x 的浅拷贝。

copy.deepcopy(x[, memo])

返回 x 的深拷贝。

异常 copy.Error

针对模块特定错误引发。

浅拷贝和深拷贝之间的区别仅与复合对象(包含其他对象的的对象,如列表或类实例)相关。

  • 浅拷贝 构造一个新的复合对象,然后(尽可能)将对原始对象中找到的对象的引用插入其中。

  • 深拷贝 构造一个新的复合对象,然后递归地将原始对象中找到的对象的副本插入其中。

深拷贝操作通常存在两个浅拷贝操作不存在的问题。

  • 递归对象(直接或间接包含对自身的引用的复合对象)可能会导致递归循环。

  • 因为深拷贝会复制所有内容,所以它可能会复制过多内容,例如打算在副本之间共享的数据。

deepcopy() 函数通过以下方式避免了这些问题:

  • 保留一个已在当前复制过程中复制的对象的 memo 字典;以及

  • 允许用户定义的类覆盖复制操作或复制的组件集。

此模块不复制模块、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口或任何类似类型。它通过返回未更改的原始对象来“复制”函数和类(浅层和深层);这与 pickle 模块处理这些类型的方式兼容。

可以使用 dict.copy() 创建字典的浅拷贝,并通过分配整个列表的切片来创建列表的浅拷贝,例如 copied_list = original_list[:]

类可以使用与控制序列化相同的接口来控制复制。有关这些方法的信息,请参阅模块 pickle 的描述。实际上,copy 模块使用来自 copyreg 模块的注册序列化函数。

为了使类定义自己的复制实现,它可以定义特殊方法 __copy__()__deepcopy__()。前者被调用来实现浅拷贝操作;不传递额外的参数。后者被调用来实现深拷贝操作;它传递一个参数,即 memo 字典。如果 __deepcopy__() 实现需要对组件进行深拷贝,它应该调用 deepcopy() 函数,将组件作为第一个参数,将 memo 字典作为第二个参数。memo 字典应被视为不透明对象。

另请参阅

模块 pickle

讨论用于支持对象状态检索和恢复的特殊方法。