用户定义 类 上复制模块的默认行为
Default behavior of copy module on user-defined classes
当在没有__copy__
或__deepcopy__
方法的用户定义class实例上调用copy.copy
or copy.deepcopy
时,Python 保证会怎样?令人不安的是,官方文档在这个问题上并不明确。该函数是否总是 return 同一个 class 的新实例与原始对象的 __dict__
的 shallow/deep 副本(或者当 __slots__
参与)? CPython、PyPy 等之间的行为会有所不同吗? Python 2 和 3 之间的行为是否不同? (忽略旧式 classes。)什么需要定义明确的 __copy__
/__deepcopy__
方法而不是使用默认行为?
参考显式(比隐式好!)需要权威声明。
通过阅读 the copy
module's source,以及其他文档,我确定了以下内容:
当 copy
或 deepcopy
在没有 __copy__
的用户定义新样式 class 的实例上调用时方法并且没有注册一个可调用的 copy_reg.pickle
, the instance's __reduce_ex__
方法被调用协议 2. object
定义了一个 __reduce_ex__
方法,它被所有新式 classes 继承不要自己定义,所以每个实例都有一个__reduce_ex__
.
__reduce_ex__
and __reduce__
return 可用于 pickling 的值,copy
模块使用这些值来模拟 unpickling,创建并 returning 一个新对象由原始对象的状态制成。此外,当使用 deepcopy
时,对象的状态(具体来说,由 __reduce_ex__
/__reduce__
编辑的元组 return 的第三个元素)在应用到新对象之前被递归地深度复制对象.
一些基本测试表明,在简单用户定义的 class returns [=28= 的实例 x
上调用 __reduce_ex__(2)
].在 Python 2 和 Python 3 中,如果 class 没有 __setstate__
方法,那么 copy
模块将执行以下等效操作:
callable, args, state, _, _ = x.__reduce_ex__(2)
y = callable(*args)
if deepcopying:
state = deepcopy(state)
y.__dict__.update(state)
return y
所以看来 copy
函数在用户定义 classes 实例上的默认行为确实是做有用且简单的事情并创建一个新对象(可能deep) 原始对象状态的副本。
当在没有__copy__
或__deepcopy__
方法的用户定义class实例上调用copy.copy
or copy.deepcopy
时,Python 保证会怎样?令人不安的是,官方文档在这个问题上并不明确。该函数是否总是 return 同一个 class 的新实例与原始对象的 __dict__
的 shallow/deep 副本(或者当 __slots__
参与)? CPython、PyPy 等之间的行为会有所不同吗? Python 2 和 3 之间的行为是否不同? (忽略旧式 classes。)什么需要定义明确的 __copy__
/__deepcopy__
方法而不是使用默认行为?
参考显式(比隐式好!)需要权威声明。
通过阅读 the copy
module's source,以及其他文档,我确定了以下内容:
当
copy
或deepcopy
在没有__copy__
的用户定义新样式 class 的实例上调用时方法并且没有注册一个可调用的copy_reg.pickle
, the instance's__reduce_ex__
方法被调用协议 2.object
定义了一个__reduce_ex__
方法,它被所有新式 classes 继承不要自己定义,所以每个实例都有一个__reduce_ex__
.__reduce_ex__
and__reduce__
return 可用于 pickling 的值,copy
模块使用这些值来模拟 unpickling,创建并 returning 一个新对象由原始对象的状态制成。此外,当使用deepcopy
时,对象的状态(具体来说,由__reduce_ex__
/__reduce__
编辑的元组 return 的第三个元素)在应用到新对象之前被递归地深度复制对象.一些基本测试表明,在简单用户定义的 class returns [=28= 的实例
x
上调用__reduce_ex__(2)
].在 Python 2 和 Python 3 中,如果 class 没有__setstate__
方法,那么copy
模块将执行以下等效操作:callable, args, state, _, _ = x.__reduce_ex__(2) y = callable(*args) if deepcopying: state = deepcopy(state) y.__dict__.update(state) return y
所以看来 copy
函数在用户定义 classes 实例上的默认行为确实是做有用且简单的事情并创建一个新对象(可能deep) 原始对象状态的副本。