pickle参考文献states that中,可以酸洗的对象集相当有限.事实上,我有一个函数返回一个动态生成的类,我发现我不能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个.好啊现在,神奇的是,如果我try pickle一个类似的对象,但它是派生类的,它会工作!

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

这里发生了什么?如果这很容易,为什么pickle不使用这个变通方法来实现一个dump方法,允许对"本地对象"进行pickle?

推荐答案

我认为你没有仔细阅读the reference you cite.参考文件还明确指出,只有以下对象是可酸洗的:

  • 在模块顶层定义的功能(使用def,而不是>;lambda)
  • 在模块顶层定义的内置函数
  • 定义为the top level of a module的类

你的例子

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

不在模块的顶层定义类,而是在f()scope范围内定义类.pickle适用于global classes类,而不是本地类.这会自动使可酸洗测试失败.

DerivedA是一门国际课程,所以一切都很好.

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

请注意,函数(内置和用户定义)是按“fully qualified” name reference而不是按值进行pickle的.这意味着只有函数名和定义函数的模块名一起被pickle.Neither the function’s code, nor any of its function attributes are pickled.因此,定义模块必须在取消勾选环境中可导入,并且该模块必须包含命名对象,否则将引发异常.

类似地,类通过命名引用进行pickle,因此在取消pickle环境中也适用相同的限制.

好了.pickle只按名称引用序列化对象,而不是按对象中包含的原始指令.这是因为pickle's的任务是序列化object hierarchy,而不是别的.

Python-3.x相关问答推荐

为什么我必须在绘制椭圆时代码等于两次?''

Pandas 中每行的最大值范围

在循环访问XML中的多个层时,xml.etree.Elementree Python3解析器不起作用

循环遍历数据框以提取特定值

如何将参数/值从测试方法传递给pytest的fixture函数?

如何使用魔杖扭曲图像

如何将项目添加到Python中具有固定大小的列表列表中

pip install saxonche v 12.1.0 产生 FileNotFoundError

转换Pandas 数据框 - 添加行

这种类型提示有什么作用?

将字典列表展平为数据框列

pymongo 失败并出现错误未定义

python tkInter 浏览文件夹按钮

如何并行化文件下载?

如何在 Python 3 中通过 IP 获取 WhoIs 信息?

Python3 mysqlclient-1.3.6(又名 PyMySQL)的用法?

cv2 python 没有 imread 成员

带有数千个逗号刻度标签的 MatPlotLib 美元符号

如何创建一个永远在其上运行滚动协程的事件循环?

Beautifulsoup 的单元测试失败