8.17. 复制-浅复制和深复制操作

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

Interface summary:

  • copy. copy(* x *)

    • 返回* x *的浅表副本。
  • copy. deepcopy(* x *)

    • 返回* x *的深层副本。
  • exception copy. error

    • 因模块特定错误而提出。

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

  • “浅拷贝”将构造一个新的复合对象,然后(在可能的范围内)将“引用” *插入到原始对象中。

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

深层复制操作通常存在两个问题,浅层复制操作通常不存在两个问题:

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

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

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

  • 保留在当前复制过程中已复制的对象的“备忘录”字典;和

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

该模块不复制诸如模块,方法,堆栈跟踪,堆栈框架,文件,套接字,窗口,数组或任何类似类型的类型。它pass不变地返回原始对象来“复制”函数和类(浅层和深层)。这与pickle模块处理这些内容的方式兼容。

可以使用dict.copy()来创建字典的浅表副本,也可以pass分配整个列表的一部分(例如copied_list = original_list[:])来创建列表的浅表副本。

在版本 2.5 中进行了更改:添加了复制Function。

类可以使用与控制 Pickling 相同的接口来控制复制。有关这些方法的信息,请参见模块pickle的描述。 copy模块不使用copy_reg注册模块。

为了让一个类定义自己的副本实现,它可以定义特殊的方法__copy__()__deepcopy__()。前者被称为实现浅拷贝操作;没有传递其他参数。后者被称为实现深度复制操作。它传递了一个参数,即备忘字典。如果__deepcopy__()实现需要复制组件的深层副本,则应调用deepcopy()函数,并将该组件作为第一个参数,并将备注字典作为第二个参数。

See also

  • Module pickle

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