I can quot;pickle local objectsquot; if I use a derived class?(我可以“腌制本地对象如果我使用派生类?)
问题描述
pickle 参考 指出可以腌制的对象集相当有限.确实,我有一个函数返回一个动态生成的类,我发现我不能pickle那个类的实例:
这样的对象对于pickle来说太复杂了.行.现在,神奇的是,如果我尝试腌制一个类似的对象,但它是派生类的,它会起作用!
这里发生了什么?如果这很简单,为什么 pickle
不使用这个变通方法来实现一个允许本地对象"被pickle 的 dump
方法?
我想你没有阅读 您引用的参考文献 仔细.该参考文献还明确指出,只有以下对象是可腌制的:
<块引用>- 在模块顶层定义的函数(使用 def,而不是 >lambda)
- 定义在模块顶层的内置函数
- 在模块顶层 定义的类
你的例子
<预><代码>>>>定义 f():... A类:通过...返回A不在模块的顶层定义类,而是在f()
的范围内定义一个类.pickle
适用于全局类,而不是本地类.这会自动通过 pickleable 测试.
DerivedA
是一个全局类,所以一切都很好.
至于为什么只有顶级(对你来说是全局的)类和函数不能被腌制,参考资料也回答了这个问题(我的粗体):
<块引用>请注意,函数(内置和用户定义的)由完全限定"名称引用而不是值来腌制.这意味着只有函数名称被腌制,以及函数在其中定义的模块的名称.函数的代码及其任何函数属性都不会被腌制.因此定义模块必须在 unpickling 环境中可导入,并且模块必须包含命名对象,否则将引发异常.
类似地,类通过命名引用进行酸洗,因此在 unpickling 环境中也适用相同的限制.
所以你有它.pickle
仅通过名称引用序列化对象,而不是通过对象中包含的原始指令序列化.这是因为 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'
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)
...
>>>
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:
- functions defined at the top level of a module (using def, not >lambda)
- built-in functions defined at the top level of a module
- classes that are defined at the top level of a module
Your example
>>> def f():
... class A: pass
... return A
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
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):
Note that functions (built-in and user-defined) are pickled by "fully qualified" name reference, not by value. This means that only the function name is pickled, along with the name of the module the function is defined in. Neither the function’s code, nor any of its function attributes are pickled. Thus the defining module must be importable in the unpickling environment, and the module must contain the named object, otherwise an exception will be raised.
Similarly, classes are pickled by named reference, so the same restrictions in the unpickling environment apply.
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.
这篇关于我可以“腌制本地对象"如果我使用派生类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:我可以“腌制本地对象"如果我使用派生类?
基础教程推荐
- 线程时出现 msgbox 错误,GUI 块 2022-01-01
- 筛选NumPy数组 2022-01-01
- 何时使用 os.name、sys.platform 或 platform.system? 2022-01-01
- 如何让 python 脚本监听来自另一个脚本的输入 2022-01-01
- 如何在海运重新绘制中自定义标题和y标签 2022-01-01
- 在 Python 中,如果我在一个“with"中返回.块,文件还会关闭吗? 2022-01-01
- 使用PyInstaller后在Windows中打开可执行文件时出错 2022-01-01
- 用于分类数据的跳跃记号标签 2022-01-01
- Dask.array.套用_沿_轴:由于额外的元素([1]),使用dask.array的每一行作为另一个函数的输入失败 2022-01-01
- Python kivy 入口点 inflateRest2 无法定位 libpng16-16.dll 2022-01-01