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

源代码: Lib/copy.py


Python 的赋值语句不复制对象,而是创建目标和对象的绑定关系。对于自身可变,或包含可变项的集合,有时要生成副本用于改变操作,而不必改变原始对象。本模块提供了通用的浅层复制和深层复制操作,(如下所述)。

接口摘要:

copy.copy(x)

返回 x 的浅层复制。

copy.deepcopy(x[, memo])

返回 x 的深层复制。

exception copy.Error

针对模块特定错误引发。

浅层与深层复制的区别仅与复合对象(即包含列表或类的实例等其他对象的对象)相关:

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

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

深度复制操作通常存在两个问题, 而浅层复制操作并不存在这些问题:

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

  • 由于深层复制会复制所有内容,因此可能会过多复制(例如本应该在副本之间共享的数据)。

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

  • 保留在当前复制过程中已复制的对象的 "备忘录" (memo) 字典;以及

  • 允许用户定义的类重载复制操作或复制的组件集合。

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, or any similar types. It does "copy" functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

制作字典的浅层复制可以使用 dict.copy() 方法,而制作列表的浅层复制可以通过赋值整个列表的切片完成,例如,copied_list = original_list[:]

类可以使用与控制序列化(pickling)操作相同的接口来控制复制操作,关于这些方法的描述信息请参考 pickle 模块。实际上,copy 模块使用的正是从 copyreg 模块中注册的 pickle 函数。

想要给一个类定义它自己的拷贝操作实现,可以通过定义特殊方法 __copy__()__deepcopy__()。 调用前者以实现浅层拷贝操作,该方法不用传入额外参数。 调用后者以实现深层拷贝操作;它应传入一个参数即 memo 字典。 如果 __deepcopy__() 实现需要创建一个组件的深层拷贝,它应当调用 deepcopy() 函数并以该组件作为第一个参数,而将 memo 字典作为第二个参数。

参见

模块 pickle

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