我可以“腌制本地对象"如果我使用派生类?

编程入门 行业动态 更新时间:2024-10-26 03:21:59
本文介绍了我可以“腌制本地对象"如果我使用派生类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

pickle 参考 指出可以腌制的对象集相当有限.确实,我有一个函数返回一个动态生成的类,我发现我不能pickle那个类的实例:

>>>进口泡菜>>>定义 f():... A类:通过...返回A...>>>本地A = f()>>>la = LocalA()>>>with open('testing.pickle', 'wb') as f:... pickle.dump(la, f, pickle.HIGHEST_PROTOCOL)...回溯(最近一次调用最后一次):文件<stdin>",第 2 行,在 <module> 中AttributeError: 无法腌制本地对象 'f.<locals>.A'

这样的对象对于pickle来说太复杂了.行.现在,神奇的是,如果我尝试腌制一个类似的对象,但它是派生类的,它会起作用!

>>>类 DerivedA(LocalA):通过...>>>da = DerivedA()>>>with open('testing.pickle', 'wb') as f:... pickle.dump(da, f, pickle.HIGHEST_PROTOCOL)...>>>

这里发生了什么?如果这很简单,为什么 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.

更多推荐

我可以“腌制本地对象"如果我使用派生类?

本文发布于:2023-06-06 05:54:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/534737.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:对象   派生类   quot

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!