PosVol = [ 0.0437 0.1680 0.2089 0.5719 0.9146 0.8306 0.8646 1.0000 0.6541 0.1628 -0.3038 -0.0990 0.3602 0.4707 0.2968 0.1793];
NegVol = [ 1.2838 1.6351 1.5026 1.1441 1.2331 1.2732 0.9188 0.1841 0.0412 0.6215 1.1444 1.0828 0.5687 0.2590 0.3917 0.5605];
PosInd = [ 1533 4057 6609 9038 11426 13831 16403 19009 21206 23609 27015 29758 32294 34789 37147 39642];
NegInd = [ 2304 4733 7283 9768 12291 14817 17397 20105 22899 25851 28218 30706 33317 36211 38628 41123];
引用states that可以被腌制的对象集相当有限。实际上,我有一个返回一个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'
而言过于复杂。好。现在,有什么神奇之处在于,如果我试图挑选一个类似的对象,而不是衍生类,它就可以了!
pickle
这里发生了什么?如果这很容易,为什么不>>> class DerivedA(LocalA): pass
...
>>> da = DerivedA()
>>> with open('testing.pickle', 'wb') as f:
... pickle.dump(da, f, pickle.HIGHEST_PROTOCOL)
...
>>>
使用此变通方法来实现允许“本地对象”被腌制的pickle
方法?
答案 0 :(得分:27)
我认为您没有仔细阅读the reference you cite。该参考文献还明确指出只有以下对象是可选择的:
- 在模块顶层定义的函数(使用def,而不是&gt; lambda)
- 在模块顶层定义的内置函数
- 在模块顶层
中定义的类
你的例子
>>> def f():
... class A: pass
... return A
没有在模块的顶层定义一个类,它在f()
的范围中定义了一个类。 pickle
适用于全局类,而非本地类。这会自动使pickleable测试失败。
DerivedA
是一个全球类,所以一切都很好。
至于为什么只能对顶层(全局到你)的类和函数进行腌制,参考文献也会回答这个问题(大胆的):
请注意,函数(内置和用户定义)由“完全限定”名称引用进行选择,而不是按值进行选择。这意味着只有函数名称被腌制,以及定义函数的模块的名称。函数的代码或其任何函数属性都不会被腌制。因此,定义模块必须可以在unpickling环境中导入,并且模块必须包含命名对象,否则将引发异常。
类似地,类通过命名引用进行pickle,因此适用于unpickling环境中的相同限制。
所以你有它。 pickle
仅按名称引用序列化对象,而不是按对象中包含的原始指令序列化。这是因为pickle's
作业是序列化对象层次结构,而不是其他任何内容。
答案 1 :(得分:17)
我不同意,你可以腌制两者。您只需要使用更好的序列化程序,例如dill
。 dill
(默认情况下)通过保存类定义来修改类,而不是通过引用进行pickling,因此它不会使您的第一个案例失败。如果愿意,您甚至可以使用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
>>>
答案 2 :(得分:2)
DerivedA
个实例是pickleable,因为DerivedA
可通过匹配其完全限定名称的全局变量获得,这就是pickle
在取消排版时查找类的方式。
尝试使用本地类执行此类操作的问题在于,没有任何标识实例所对应的 A
类。如果你运行f
两次,你会得到两个A
类,并且没有办法告诉哪一个应该是来自另一个程序运行的未标记A
实例的类。如果您根本没有运行f
,那么您将获得 no A
类,然后您对未修改的实例的类型做了什么?
答案 3 :(得分:2)
您只能腌制在模块顶层定义的类的实例。
但是,如果将本地定义的类的实例提升为顶级,则可以使它们腌制。
您必须设置本地类的 __ 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