问题描述
pickle
参考状态可以腌制的对象集非常有限.确实,我有一个函数可以返回一个由数学生成的类,但是我发现我无法腌制该类的实例:
The pickle
reference states that the set of objects which can be pickled is rather limited. Indeed, I have a function which returns a dinamically-generated class, and I found I can't pickle instances of that class:
>>> import pickle
>>> def f():
... class A: pass
... return A
...
>>> LocalA = f()
>>> la = LocalA()
>>> with open('testing.pickle', 'wb') as f:
... pickle.dump(la, f, pickle.HIGHEST_PROTOCOL)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: Can't pickle local object 'f.<locals>.A'
对于pickle
来说,这样的对象太复杂了.好的.现在,神奇的是,如果我尝试腌制一个类似的对象但属于派生类,它会起作用!
Such objects are too complicated for pickle
. Ok. Now, what's magic is that, if I try to pickle a similar object, but of a derived class, it works!
>>> class DerivedA(LocalA): pass
...
>>> da = DerivedA()
>>> with open('testing.pickle', 'wb') as f:
... pickle.dump(da, f, pickle.HIGHEST_PROTOCOL)
...
>>>
这是怎么回事?如果这样简单,为什么pickle
不使用此替代方法来实现允许腌制本地对象"的dump
方法?
What's happening here? If this is so easy, why doesn't pickle
use this workaround to implement a dump
method that allows "local objects" to be pickled?
推荐答案
我认为您没有阅读您仔细引用的参考文献.该参考文献还明确指出,只有以下对象是可腌制的:
I think you did not read the reference you cite carefully. The reference also clearly states that only the following objects are pickleable:
您的示例
>>> def f():
... class A: pass
... return A
未在模块的顶层定义类,而是在f()
的范围中定义了一个类. pickle
适用于全局类,而不适用于本地类.这将自动使可腌制测试失败.
does not define a class at the top level of a module, it defines a class within the scope of f()
. pickle
works on global classes, not local classes. This automatically fails the pickleable test.
DerivedA
是全局类,所以一切都很好.
DerivedA
is a global class, so all is well.
至于为什么只有顶级(对您来说是全局的)类和函数不能被腌制,参考文献也回答了这个问题(黑体字):
As for why only top-level (global to you) classes and functions can't be pickled, the reference answers that question as well (bold mine):
类似地,通过命名引用对类进行酸洗,因此在未酸洗环境中也适用相同的限制.
Similarly, classes are pickled by named reference, so the same restrictions in the unpickling environment apply.
因此,您已经拥有了. pickle
仅通过名称引用而不是对象中包含的原始指令来序列化对象.这是因为pickle's
的工作是序列化对象层次结构,而别无其他.
So there you have it. pickle
only serialises objects by name reference, not by the raw instructions contained within the object. This is because pickle's
job is to serialise object hierarchy, and nothing else.
这篇关于我可以“刺本地对象".如果我使用派生类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!