欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

源码阅读 | Python中copy.deepcopy原理

程序员文章站 2022-03-10 22:24:57
介绍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

相关标签: python 代码阅读