泡菜和深度复制之间的关系 [英] Relationship between pickle and deepcopy
问题描述
pickle
和copy.deepcopy
之间的确切关系是什么?它们共享哪些机制,以及如何共享?
What exactly is the relationship between pickle
and copy.deepcopy
? What mechanisms do they share, and how?
很明显,这两个是密切相关的操作,并且共享一些机制/协议,但是我无法将细节笼罩着.
It is clear the two are closely-related operations, and share some of the mechanisms/protocols, but I can't wrap my head around the details.
我发现的一些(令人困惑的)东西
Some (confusing) things I found out:
- 如果类定义了
__[gs]etstate__
,则会在其实例的deepcopy
上调用它们.一开始这让我感到惊讶,因为我认为它们特定于pickle
,但是后来我发现 类可以使用与控制酸洗相同的界面来控制复制 .但是,没有关于深度复制时如何使用__[gs]etstate__
的文档(如何使用从__getstate__
返回的值,是什么传递给__setstate__
?) -
deepcopy
的幼稚替代实现为pickle.loads(pickle.dumps(obj))
.但是,这可能不等同于深度复制,因为如果类定义了__deepcopy__
操作,则不会使用此基于pickle的深度复制实现来调用它. (我也偶然发现了一种说法,即深拷贝比pickle更通用,并且有许多类型是可深拷贝的,但不能进行pickle.)
- If a class defines
__[gs]etstate__
, they get called upon adeepcopy
of its instances. This surprised me at first, because I thought they are specific topickle
, but then I found that Classes can use the same interfaces to control copying that they use to control pickling. However, there's no documentation of how__[gs]etstate__
is used when deepcopying (how the value returned from__getstate__
is used, what is being passed to__setstate__
?) - A naive alternative implementation of
deepcopy
would bepickle.loads(pickle.dumps(obj))
. However, this can't possibly be equivalent to deepcopy'ing, because if a class defines a__deepcopy__
operation, it would not be invoked using this pickle-based implementation of deepcopy. (I also stumbled upon a statement that deepcopy is more general than pickle, and there are many types which are deepcopyable, but not pickleable.)
(1)表示共性,而(2)表示pickle
和deepcopy
之间的差异.
(1) indicates a commonality, while (2) indicates a difference between pickle
and deepcopy
.
最重要的是,我发现了以下两个矛盾的说法:
On top of that, I found these two contradictory statements:
copy_reg :酸洗,cPickle和复制模块在酸洗/复制这些对象时会使用这些功能.
copy_reg: The pickle, cPickle, and copy modules use those functions when pickling/copying those objects
和
复制模块未使用copy_reg注册模块
The copy module does not use the copy_reg registration module
一方面,这是pickle
和deepcopy
之间的关系/共性的另一种指示,另一方面,这加剧了我的困惑...
This, on one hand, is another indication of a relationship/commonality between pickle
and deepcopy
, and on the other hand, contributes to the my confusion...
[我的经验是使用python2.7,但是我也很感谢有关python2和python3之间的pickle/deepcopy差异的任何指点]
推荐答案
您不应被(1)和(2)所迷惑.通常,Python会尝试为遗漏的方法提供合理的后备方法. (例如,定义__getitem__
以便具有可迭代的类就足够了,但是也可以实现__iter__
效率更高.类似于__add__
的操作,并带有可选的__iadd__
等.)
You should not be confused by (1) and (2). In general, Python tries to include sensible fall-backs for missing methods. (For instance, it is enough to define __getitem__
in order to have an iterable class, but it may be more efficient to also implement __iter__
. Similar for operations like __add__
, with optional __iadd__
etc.)
__deepcopy__
是deepcopy()
会寻找的最专门的方法,但是,如果它不存在,则退回使用pickle协议是明智的选择.它并没有真正调用dumps()
/loads()
,因为它不依赖中间表示形式为字符串,而是像您一样间接使用__getstate__
和__setstate__
(通过__reduce__
).观察到.
__deepcopy__
is the most specialized method that deepcopy()
will look for, but if it does not exists, falling back to the pickle protocol is a sensible thing to do. It does not really call dumps()
/loads()
, because it does not rely on the intermediate representation to be a string, but it will indirectly make use of __getstate__
and __setstate__
(via __reduce__
), as you observed.
当前,文档仍然说明
...复制模块不使用copy_reg注册模块.
… The copy module does not use the copy_reg registration module.
,但这似乎是同时已修复的错误(可能是2.7分支)在这里没有引起足够的重视.)
but that seems to be a bug that has been fixed in the meantime (possibly, the 2.7 branch has not gotten enough attention here).
还请注意,这已经非常深入地集成到了Python中(至少现在是这样); object
类本身实现了__reduce__
(及其版本化的_ex变体),它引用copy_reg.__newobj__
来创建给定对象派生类的新实例.
Also note that this is pretty deeply integrated into Python (at least nowadays); the object
class itself implements __reduce__
(and its versioned _ex variant), which refers to copy_reg.__newobj__
for creating fresh instances of the given object-derived class.
这篇关于泡菜和深度复制之间的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!