8.17. copy — 浅层 (shallow) 和深层 (deep) 复制操作

Python 中赋值语句不复制对象,而是在目标和对象之间创建绑定 (bindings) 关系。对于自身可变或者包含可变项的集合对象,开发者有时会需要生成其副本用于改变操作,进而避免改变原对象。本模块提供了通用的浅层复制和深层复制操作(如下所述)。

接口摘要:

copy.copy(x)

返回 x 的浅层复制。

copy.deepcopy(x)

返回 x 的深层复制。

exception copy.error

针对模块特定错误引发。

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

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

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

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

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

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

The deepcopy() function avoids these problems by:

  • keeping a “memo” dictionary of objects already copied during the current copying pass; and

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

该模块不复制模块、方法、栈追踪(stack trace)、栈帧(stack frame)、文件、套接字、窗口、数组以及任何类似的类型。它通过不改变地返回原始对象来(浅层或深层地)“复制”函数和类;这与 pickle 模块处理这类问题的方式是相似的。

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

在 2.5 版更改: Added copying functions.

Classes can use the same interfaces to control copying that they use to control pickling. See the description of module pickle for information on these methods. The copy module does not use the copy_reg registration module.

In order for a class to define its own copy implementation, it can define special methods __copy__() and __deepcopy__(). The former is called to implement the shallow copy operation; no additional arguments are passed. The latter is called to implement the deep copy operation; it is passed one argument, the memo dictionary. If the __deepcopy__() implementation needs to make a deep copy of a component, it should call the deepcopy() function with the component as first argument and the memo dictionary as second argument.

参见

模块 pickle

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