Python中的赋值表达式并不会赋值对象,只是创建目标和对象之间的绑定。本模块提供通用浅和深拷贝操作。
浅拷贝和深拷贝只和复合对象有关:
- 浅拷贝构造一个新的复合对象,然后(在可能的范围内)向其中插入对原始对象中的对象的引用。
- 深拷贝构造一个新的复合对象,然后递归地向其中插入对原始对象的复制(不同于原对象)。
两个常见于深拷贝而不存在于浅拷贝的问题:
- 递归对象(那些直接或间接包含自身引用的复合对象)可能导致递归循环。
- 因为深拷贝复制任何内容,它可能复制太多内容,而这些内容可能用于在复制中共享。
但copy.deepcopy()
函数避免了这些问题,通过:
- 维护一个字典memo,这个字典保存了之前复制过的对象。
- 让用户自定义类重写复制操作或复制组件集。
本模块可复制的内容和pickle
模块所定义兼容。
字典的浅拷贝可通过dict.copy()
,而列表的浅拷贝可通过切片copied_list = original_list[:]
。
类可通过使用控制序列化相同的接口控制复制。如__reduce_ex__(version)
和__reduce__()
。
类可以通过实现复制协议定义自身复制实现。__copy__()
实现浅拷贝,__deepcopy__()
实现深拷贝。
浅拷贝
浅拷贝的实现:
- 对于常见的不可变类型(如
int
等)和可变类型(如list
等)等,通过类型从_copy_dispatch
映射中获取复制函数进行浅拷贝操作。 - 其他类型如自定义的类,如果实现了
__copy__()
则调用该方法进行浅拷贝;如果copyreg
模块中的dispatch_table
映射有该类型的复制函数,则调用该函数进行浅拷贝;如果实现了序列化协议(如__reduce_ex__()
和__reduce__()
)则调用该方法进行浅拷贝。
import types
import weakref
from copyreg import dispatch_table
def copy(x):
"""Shallow copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
cls = type(x)
copier = _copy_dispatch.get(cls)
# 如果是常见类型,如不可变类型int,可变类型list,
# 直接通过复制函数进行拷贝操作。
if copier:
return copier(x)
if issubclass(cls, type):
# treat it as a regular class:
return _copy_immutable(x)
# 如果该对象实现浅拷贝协议,则通过浅拷贝
# 特殊方法实现拷贝操作。
copier = getattr(cls, "__copy__", None)
if copier is not None:
return copier(x)
# 从copyreg获取对应类型的复制函数
reductor = dispatch_table.get(cls)
if reductor is not None:
rv = reductor(x)
else:
# 从__reduce_ex__中获取对应的压缩方法,
# 这个是序列化协议的内容,但可用于拷贝操作,
# 继承object的类默认实现该方法
reductor = getattr(x, "__reduce_ex__", None)
if reductor is not None:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error("un(shallow)copyable object of type %s" % cls)
if isinstance(rv, str):
return x
# _reconstruct函数在浅拷贝中主要是通过
#