copy
--- 浅层和深层复制操作¶
源代码: Lib/copy.py
Python 中的赋值语句不复制对象,而是在目标和对象之间创建绑定。对于可变或包含可变项的集合,有时需要副本,以便可以更改一个副本而无需更改另一个。本模块提供了通用的浅层和深层复制操作(如下所述)。
接口摘要
- copy.copy(obj)¶
返回 obj 的浅层复制。
- copy.deepcopy(obj[, memo])¶
返回 obj 的深层复制。
- copy.replace(obj, /, **changes)¶
创建一个与 obj 类型相同的新对象,并用 changes 中的值替换字段。
在 3.13 版本加入。
- exception copy.Error¶
针对模块特定错误引发。
浅层和深层复制之间的区别仅与复合对象(包含其他对象,如列表或类实例的对象)有关:
浅层复制 会创建一个新的复合对象,然后(在可能的范围内)将原始对象中元素的 引用 插入其中。
深层复制 会创建一个新的复合对象,然后递归地将原始对象中元素的 副本 插入其中。
深层复制操作通常存在两个浅层复制操作不存在的问题:
递归对象(直接或间接包含对自身引用的复合对象)可能会导致递归循环。
因为深层复制会复制所有内容,所以它可能会复制过多的数据,例如本应在副本之间共享的数据。
deepcopy()
函数通过以下方式避免了这些问题:
保留一个
memo
字典,用于记录在当前复制过程中已复制的对象;以及让用户自定义的类可以重写复制操作或要复制的组件集。
此模块不复制模块、方法、栈跟踪、栈帧、文件、套接字、窗口或任何类似类型。它确实“复制”了函数和类(浅层和深层),通过返回原始对象而不做改变;这与 pickle
模块处理这些类型的方式是兼容的。
字典的浅层复制可以使用 dict.copy()
来创建,列表的浅层复制可以通过对整个列表进行切片赋值来创建,例如 copied_list = original_list[:]
。
类可以使用与控制 pickling 相同的接口来控制复制。有关这些方法的信息,请参阅 pickle
模块的描述。事实上,copy
模块使用了来自 copyreg
模块中已注册的 pickle 函数。
为了让一个类定义自己的复制实现,它可以定义特殊方法 __copy__()
和 __deepcopy__()
。
- object.__copy__(self)¶
调用以实现浅层复制操作;不传递额外参数。
- object.__deepcopy__(self, memo)¶
调用以实现深层复制操作;它被传递一个参数,即 memo 字典。如果
__deepcopy__
的实现需要对一个组件进行深层复制,它应该调用deepcopy()
函数,并将该组件作为第一个参数,memo 字典作为第二个参数。memo 字典应被视为一个不透明对象。
函数 copy.replace()
比 copy()
和 deepcopy()
功能更受限,只支持由 namedtuple()
创建的命名元组、dataclasses
以及其他定义了 __replace__()
方法的类。
- object.__replace__(self, /, **changes)¶
此方法应创建一个相同类型的新对象,并用 changes 中的值替换字段。
在 3.13 版本加入。
参见
pickle
模块关于用于支持对象状态获取和恢复的特殊方法的讨论。