pickle
和{
很明显,这两个操作是密切相关的,并且共享一些机制/协议,但是我不能把我的头脑集中在细节上。在
我发现了一些(令人困惑的)事情:
__[gs]etstate__
,它们将被调用其实例的deepcopy
。一开始这让我很惊讶,因为我认为它们是pickle
特有的,但后来我发现了Classes can use the same interfaces to control copying that they use to control pickling。然而,对于深度复制(如何使用__getstate__
返回的值,传递给__setstate__
的值是如何使用的)时,如何使用__[gs]etstate__
的文档在deepcopy
的另一个简单的实现是pickle.loads(pickle.dumps(obj))
。但是,这不可能等同于deepcopy'ing,因为如果一个类定义了一个__deepcopy__
操作,那么就不会使用deepcopy的这种基于pickle的实现来调用它。(我还偶然发现了一个声明,deepcopy比pickle更通用,而且有许多类型可以deepcopy,但不能pickle。)(1)表示共性,而(2)表示pickle
和{
除此之外,我还发现了两种相互矛盾的说法:
copy_reg: The pickle, cPickle, and copy modules use those functions when pickling/copying those objects
以及
The copy module does not use the copy_reg registration module
一方面,这是pickle
和{
[我的经验是使用python2.7,但我也希望能提供关于python2和python3在pickle/deepcopy上的差异的任何建议]
你不应该被(1)和(2)混淆。一般来说,Python会尝试为丢失的方法包含合理的回退。(例如,定义
__getitem__
以拥有iterable类就足够了,但是实现__iter__
可能更有效。类似于__add__
,可选的__iadd__
等。)__deepcopy__
是deepcopy()
要寻找的最专门的方法,但是如果它不存在,返回pickle协议是一件明智的事情。它并没有真正地调用dumps()
/loads()
,因为它不依赖中间表示作为字符串,而是间接地使用__getstate__
和{__reduce__
)。在当前,the documentation仍处于状态
但这似乎是a bug that has been fixed in the meantime(可能,2.7分支在这里没有得到足够的关注)。在
还要注意的是,这已经非常深入地集成到Python中了(至少现在是这样)}来创建给定对象派生类的新实例。在
object
类本身实现了__reduce__
(及其版本化的_-ex-variant),它引用{好吧,我不得不读了这篇文章的源代码,但看起来这是一个非常简单的答案。 http://svn.python.org/projects/python/trunk/Lib/copy.py
copy
查找一些它知道构造函数是什么样子的内置类型(注册在_copy_dispatch
字典中,当它不知道如何复制基本类型时,它导入copy_reg.dispatch_table
。。。这是pickle
注册它所知道的生成对象新副本的方法的地方。本质上,它是一个关于对象类型和“生成新对象的函数”这个“生成新对象的函数”与您为一个对象编写__reduce__
或__reduce_ex__
方法时编写的内容(如果其中一个丢失或需要帮助,它将遵循__setstate__
、__getstate__
等方法。在这就是
copy
。基本上…(有一些附加条款…)deepcopy
执行与上述相同的操作,但除此之外,还要检查每个对象并确保每个新对象都有一个副本,而不是指针引用。deepcopy
构建它自己的_deepcopy_dispatch
表(dict),它在其中注册函数,以确保生成的新对象没有指向原始对象的指针引用(可能是用copy_reg.dispatch_table
中注册的__reduce__
函数生成的)因此,编写一个}也能完成它们的工作。在
__reduce__
方法(或类似方法)并将其注册到copy_reg
中,应该可以使copy
和{相关问题 更多 >
编程相关推荐