源码阅读 | Python中copy.deepcopy原理
程序员文章站
2022-07-03 19:21:55
介绍deepcopy是用来进行深层复制的, 但是在实际中可能遇到, 复制一个对象后, 某些属性没了, 因此看看源码, 顺便记录下来.Python 版本: 3.6copy模块位置: copy.py (Python的lib包里面)源码注释"""deepcopy的主要逻辑在下面的函数.deepcopy的文档: https://docs.python.org/3/library/copy.html"""def deepcopy(x, memo=None, _nil=[]): """Dee...
介绍
deepcopy是用来进行深层复制的, 但是在实际中可能遇到, 复制一个对象后, 某些属性没了, 因此看看源码, 顺便记录下来.
Python 版本: 3.6
copy模块位置: copy.py (Python的lib包里面)
源码注释
"""
deepcopy的主要逻辑在下面的函数.
deepcopy的文档: https://docs.python.org/3/library/copy.html
"""
def deepcopy(x, memo=None, _nil=[]):
"""Deep copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
if memo is None:
memo = {}
# memo 用于记录对象是否被复制过了, 可以防止对象出现循环引用导致无限复制的情景.
d = id(x)
y = memo.get(d, _nil)
if y is not _nil:
return y
cls = type(x)
copier = _deepcopy_dispatch.get(cls) # 一些内置的数据类型有特定的复制函数, 比如list等, 在copy.py中可以找到其定义.
if copier:
y = copier(x, memo)
else:
try:
issc = issubclass(cls, type) # int, float等类型, 在复制的时候直接是自身, 因此不用特别的进行复制.
except TypeError: # cls is not a class (old Boost; see SF #502085)
issc = 0
if issc:
y = _deepcopy_atomic(x, memo)
else:
copier = getattr(x, "__deepcopy__", None)
if copier:
y = copier(memo) # 对象可以自己定义deepcopy的逻辑
else:
# 如果没有定义, 则通过reduce进行对象的深层复制. reduce和_reconstruct是对应的, reduce是对象的序列化, _reconstruct是根据对象的序列化表示构建对象. 这里是deepcopy的关键, 关于序列化和反序列化的操作, 和pickle的逻辑是一样的. 参考 pickle的文档: https://docs.python.org/3/library/pickle.html
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error(
"un(deep)copyable object of type %s" % cls)
# 重新构建对象
if isinstance(rv, str):
y = x
else:
y = _reconstruct(x, memo, *rv)
# If is its own copy, don't memoize.
if y is not x:
memo[d] = y
_keep_alive(x, memo) # Make sure x lives at least as long as d
return y
"""
_reconstruct是根据reduce得到的对象表示进行构建对象. 在deepcopy的情况下, 是复制对象序列化的表示, 然后根据这个表示构建对象的复制, 整个过程是迭代进行的.
"""
def _reconstruct(x, memo, func, args,
state=None, listiter=None, dictiter=None,
deepcopy=deepcopy):
deep = memo is not None
if deep and args:
args = (deepcopy(arg, memo) for arg in args)
y = func(*args) # 对象的构建, 除了x, 和memo, 其他几个参数都是reduce得到的, 这里调用函数func默认是内置的, 不是对象的构造函数(__init__).
if deep:
memo[id(x)] = y
if state is not None:
if deep:
state = deepcopy(state, memo)
if hasattr(y, '__setstate__'):
y.__setstate__(state) # setstate的语义见pickle的文档.
else:
if isinstance(state, tuple) and len(state) == 2:
state, slotstate = state
else:
slotstate = None
if state is not None:
y.__dict__.update(state)
if slotstate is not None:
for key, value in slotstate.items():
setattr(y, key, value)
if listiter is not None:
if deep:
for item in listiter:
item = deepcopy(item, memo)
y.append(item)
else:
for item in listiter:
y.append(item)
if dictiter is not None:
if deep:
for key, value in dictiter:
key = deepcopy(key, memo)
value = deepcopy(value, memo)
y[key] = value
else:
for key, value in dictiter:
y[key] = value
return y
本文地址:https://blog.csdn.net/feifei3211/article/details/111937002
上一篇: 腾讯视频首推中视频战略:更多、更爽、更广
下一篇: c#学习笔记 里氏替换原则 is和as