python – 用户定义的类上的复制模块的默认行为

当在没有__copy__或__deepcopy__方法的用户定义类的实例上调用
copy.copy
copy.deepcopy时,Python保证会发生什么?官方文件在这个问题上令人不安地不明确.函数是否总是只返回同一个类的新实例,其中包含原始对象的__dict__的浅/深副本(或者涉及__slots__时的等效内容)? CPython,PyPy等之间的行为会有所不同吗? Python 2和3之间的行为有何不同? (忽略旧式类.)什么会使人们需要定义显式__copy __ / __ deepcopy__方法而不是使用默认行为?

需要引用显式(优于隐式!)权威语句.

最佳答案 从阅读到
the copy module’s source,以及其他文件,我已确定以下内容:

>如果在没有__copy__方法的用户定义的新样式类的实例上调用copy或deepcopy,并且没有使用copy_reg.pickle注册可调用,则使用协议2调用实例的__reduce_ex__方法.对象定义了__reduce_ex__方法由所有未定义自己的新类继承,因此每个实例都有__reduce_ex__.
> __reduce_ex__ and __reduce__返回值可用于酸洗,复制模块使用这些值来模拟unpickling,创建&返回由原始对象的状态构成的新对象.此外,在使用deepcopy时,对象的状态(具体地说,__reduce_ex __ / __ reduce__返回的元组的第三个元素)在将其应用于新对象之前会以递归方式进行深度复制.
>一些基本测试表明,在一个简单的用户定义类的实例x上调用__reduce_ex __(2)会返回(< function __newobj __>,(type(x),),x .__ dict __,None,None).在Python 2和Python 3中,如果类没有__setstate__方法,则复制模块将执行以下等效操作:

callable, args, state, _, _ = x.__reduce_ex__(2)
y = callable(*args)
if deepcopying:
    state = deepcopy(state)
y.__dict__.update(state)
return y

因此,似乎复制函数在用户定义类的实例上的默认行为确实是有用的&简单的事情,并创建一个新对象与原始对象的状态的(可能深)副本.

点赞