我有一个类,如下所示,继承自datetime.date
class my_class(datetime.date):
def __new__(cls, arg1=None):
print ("arg1: ", arg1)
return super().__new__(cls, 2015, 11, 2)
当我copy
(或deepcopy
)此类的一个实例时,如下所示
import copy
my_obj = my_class(5)
copy.copy(my_obj)
我得到以下输出
arg1: 5
arg1: b'\x07\xdf\x0b\x02'
很明显,在执行bytes
(或copy
)时,一些deepcopy
对象作为第一个参数传递。我知道copy
函数的工作原理是将参数传递给相关对象的构造函数,以便创建一个相同的对象...那么为什么它会传递这些bytes
个对象?
这种行为似乎只在从不可变对象继承时才会发生,因为当我从list
对象继承时测试它时,copy
函数没有传递bytes
对象。 / p>
(注意我上面定义的类是我正在使用的真实类的非常(非常!)简化情况,它也继承自datetime.date
)
提前致谢
注意
我正在使用Python 3.5.1
答案 0 :(得分:1)
发生这种情况的原因是内部copy
和deepcopy
使用pickle
来促进对象状态序列化。来自docs:
此模块不复制模块,方法,堆栈跟踪,堆栈帧,文件,套接字,窗口,数组或任何类似类型等类型。它通过返回原始对象来“复制”函数和类(浅和深);这与pickle模块处理这些方式兼容。
...
实际上,
copy
模块使用pickle
模块中已注册的copyreg
函数。
为什么copy
需要pickle
?这是因为:
浅拷贝构造一个新的复合对象,然后(尽可能)将对它的引用插入到原始对象中找到的对象。
为此,copy
需要能够理解对象层次结构。 Pickling旨在通过将层次结构映射到标准序列化格式来解决该问题。
这也是字节对象的来源。
“Pickling”是将Python对象层次结构转换为字节流的过程,而“unpickling”是反向操作,其中字节流(来自二进制文件或类似字节)对象)被转换回对象层次结构。
看来,无论出于何种原因(也许datetime.date
以特殊的方式实现__new__
?),unpickling不会再现传递给__new__
的整数参数。
为什么呢?我没有世俗的想法。捅了一下,看看你能挖出什么。
如果copy()
或deepcopy()
对您行为不端,文档也很清楚该怎么做 - 定义您自己的副本实现!
为了让类定义自己的副本实现,它可以定义特殊方法
__copy__()
和__deepcopy__()
。前者被称为实现浅拷贝操作;没有传递其他参数。
调用后者来实现深拷贝操作;它传递了一个参数,即备忘录字典。
如果
__deepcopy__()
实现需要对组件进行深层复制,则应调用deepcopy()
函数,并将组件作为第一个参数,将备注字典作为第二个参数。