当前位置: 首页 > 面试题库 >

如果使用派生类,我可以“刺本地对象”吗?

慕容昊焜
2023-03-14
问题内容

pickle参考文献指出,可以腌制的对象集相当有限。确实,我有一个函数可以返回一个由数学生成的类,但发现无法腌制该类的实例:

>>> 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。好。现在,神奇的是,如果我尝试腌制相似的对象但属于派生类,它会起作用!

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

这里发生了什么事?如果这样简单,为什么不pickle使用此替代方法来实现dump允许“本地对象”被腌制的方法呢?


问题答案:

我认为您没有仔细阅读您引用的参考文献。该参考文献还明确指出只有以下对象是可腌制的:

  • 在模块顶层定义的函数(使用def,而不是> lambda)
  • 在模块顶层定义的内置函数
  • 模块顶层* 定义的类 *

你的例子

>>> def f():
...     class A: pass
...     return A

在模块的顶部电平不定义类,它定义了一个内类 范围f()pickle适用于 全局类 ,而不是局部类。这将自动使可腌制测试失败。

DerivedA 是一个全球课程,所以一切都很好。

至于为什么只有顶级(对您来说是全局的)类和函数不能被腌制,参考文献也回答了这个问题(黑体字):

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

同样,通过命名引用对类进行酸洗,因此在未酸洗环境中也适用相同的限制。

所以你有它。pickle仅按名称引用而不是对象中包含的原始指令序列化对象。这是因为pickle's工作是序列化 对象层次结构 ,而没有别的。



 类似资料:
  • 每个类中的方法如下所示: }

  • #include <iostream> using namespace std; class Shape { public: virtual void draw () {} }; class Circle : public Shape { int radius; public: Circle () { radius = 1; } void draw () { cout <<

  • 尽管派生类对象也是基类对象,但是派生类类型和基类类型是不同的。在 public 继承中,派生类对象能作为基类对象处理。由于派生类具有对应每个基类成员的成员(派生类的成员通常比基类的成员多),所以把派生类的对象赋给基类对象是合理的。但是,反过来赋值会使派生类中基类不具有的成员没有定义,所以这是不允许的。尽管如此,提供正确的重载赋值运算符和(或)转换构造函数可以允许这种操作(见第8章)。 常见编程错误

  • PooledObjectFactory的创建方法没有参数 https://commons.apache.org/proper/commons-pool/api-2.4.2/org/apache/commons/pool2/BasePooledObjectFactory.html#create-- 如果我的Foo类定义是: 这个Foo可以通过公共池汇集吗? 谢谢你的任何建议

  • 问题内容: 为什么在C#中,不允许派生类具有比其基类更大的可访问性。 例如,这将产生错误:可访问性不一致:与“ DerivedClass”类相比,基类“ BaseClass”的访问性较差 以及为什么在Java中允许它。 问题答案: 更新 :这个问题是我在2012年11月13日发布的博客的主题。感谢您提出的好问题! 为什么在C#中,不允许派生类具有比其基类更大的可访问性? 除了其他好的答案之外,请考

  • 除了我想让我的cherrypy服务器启动两个类之外,我还将遵循cherrypy教程“让它Rest一下”:一个用于服务一些静态文件,另一个用于RESTful API: api.py: 服务器py: 但是,当我启动服务器()并在上执行GET时,我会得到这个错误: 500内部服务器错误 服务器遇到意外情况,无法满足请求。 Traceback(最近的最后一次调用):File"/usr/local/lib/