fon*_*ini 25 python nested pickle python-3.x
该pickle参考文献指出可以酸洗的物体组是相当有限的.实际上,我有一个函数返回一个dinamically生成的类,我发现我不能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'
Run Code Online (Sandbox Code Playgroud)
这些对象太复杂了pickle.好.现在,有什么神奇的,如果我试图挑选一个类似的对象,但是派生类,它就可以了!
>>> class DerivedA(LocalA): pass
...
>>> da = DerivedA()
>>> with open('testing.pickle', 'wb') as f:
... pickle.dump(da, f, pickle.HIGHEST_PROTOCOL)
...
>>>
Run Code Online (Sandbox Code Playgroud)
这里发生了什么事?如果这很容易,为什么不pickle使用这种解决方法来实现一个dump允许"本地对象"被腌制的方法?
Aks*_*jan 34
我想你没有仔细阅读你引用的参考文献.该参考文献还明确指出只有以下对象可以选择:
- 在模块的顶层定义的函数(使用def,而不是> lambda)
- 在模块顶层定义的内置函数
- 在模块顶层定义的类
你的榜样
>>> def f():
... class A: pass
... return A
Run Code Online (Sandbox Code Playgroud)
在模块的顶部电平不定义类,它定义了一个内类范围的f().pickle适用于全局类,而不是本地类.这会自动使pickleable测试失败.
DerivedA 是全球一流的,所以一切都很好.
至于为什么只有顶层(全局到你)的类和函数不能被腌制,参考文献也回答了这个问题(大胆的):
请注意,函数(内置和用户定义)由"完全限定"的名称引用而非值引用.这意味着只有函数名称被腌制,以及定义函数的模块的名称.函数的代码或其任何函数属性都不会被pickle.因此,定义模块必须可以在unpickling环境中导入,并且模块必须包含命名对象,否则将引发异常.
类似地,类通过命名引用进行pickle,因此适用于unpickling环境中的相同限制.
所以你有它.pickle仅按名称引用序列化对象,而不是通过对象中包含的原始指令.这是因为pickle's作业是序列化对象层次结构,而不是其他任何东西.
Mik*_*rns 19
我不同意,你可以腌制两者.你只需要使用更好的序列化器,比如dill. dill(默认情况下)通过保存类定义而不是通过引用进行pickle来修改类,因此它不会使第一种情况失败.dill如果愿意,您甚至可以使用获取源代码.
>>> import dill as pickle
>>> def f():
... class A: pass
... return A
...
>>> localA = f()
>>> la = localA()
>>>
>>> _la = pickle.dumps(la)
>>> la_ = pickle.loads(_la)
>>>
>>> class DerivedA(localA): pass
...
>>> da = DerivedA()
>>> _da = pickle.dumps(da)
>>> da_ = pickle.loads(_da)
>>>
>>> print(pickle.source.getsource(la_.__class__))
class A: pass
>>>
Run Code Online (Sandbox Code Playgroud)
您只能腌制在模块顶级定义的类的实例。
但是,如果将本地定义的类的实例提升到顶级,则可以选择它们。
您必须设置本地类的__ qualname__类属性。然后,您必须将该类分配给同名的顶级变量。
def define_class(name):
class local_class:
pass
local_class.__qualname__ = name
return local_class
class_A = define_class('class_A') # picklable
class_B = define_class('class_B') # picklable
class_X = define_class('class_Y') # unpicklable, names don't match
Run Code Online (Sandbox Code Playgroud)