我可以“刺本地对象".如果我使用派生类? [英] I can "pickle local objects" if I use a derived class?

查看:65
本文介绍了我可以“刺本地对象".如果我使用派生类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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,而不是> lambda)
  • 在模块顶层定义的内置函数
  • 模块顶级 上定义的
  • 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

您的示例

>>> 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):

请注意,函数(内置的和用户定义的)是通过完全限定"名称引用而不是通过值来腌制的.这意味着仅对功能名称以及定义该功能的模块的名称进行了酸洗.既不对函数的代码也不对其任何函数属性进行酸洗.因此,定义模块必须可以在解开环境中导入,并且该模块必须包含命名对象,否则将引发异常.

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.

因此,您已经拥有了. 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.

这篇关于我可以“刺本地对象".如果我使用派生类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆