从SimpleNamespace派生类的pickle.load上出现TypeError



考虑以下Python(3.5版(代码:

import pickle
from types import SimpleNamespace
class MyClass1(list):
def __init__(self, x):
self.append(x)
class MyClass2(SimpleNamespace):
def __init__(self, x):
self.x = x
a0 = SimpleNamespace(x=99)
a1 = MyClass1(99)
a2 = MyClass2(99)
print('* SimpleNamespace:', pickle.loads(pickle.dumps(a0)))
print('* MyClass1:', pickle.loads(pickle.dumps(a1)))
print('* MyClass2:', pickle.loads(pickle.dumps(a2)))

这对前两个(a0和a1(来说很好,但在处理a2时,我得到了一个错误:

* SimpleNamespace: namespace(x=99)
* MyClass1: [99]
Traceback (most recent call last):
File "./picktest.py", line 20, in <module>
print('* MyClass2:', pickle.loads(pickle.dumps(a2)))
TypeError: __init__() missing 1 required positional argument: 'x'

观察结果:

  • SimpleNamespace可以进行腌制
  • 从不同类型(list(派生的类可以(取消(腌制
  • 如果从SimpleNamespace派生的类具有需要参数的__init__,则无法取消拾取该类。(错误发生在pickle.loads中(

请注意,我尝试用pass替换self.x = x,但这并没有改变任何内容。

除了在没有继承的情况下重新实现MyClass2之外,还有什么方法可以实现这一点吗?

问题是SimpleNamespace定义了一个__reduce__pickle使用它来取消拾取对象。但是,SimpleNamespace中定义的__reduce__与您的__init__不一致。你可以定义你自己的__reduce__来绕过这个:

import pickle
from types import SimpleNamespace
class MyClass1(list):
def __init__(self, x):
self.append(x)
class MyClass2(SimpleNamespace):
def __init__(self, x):
self.x = x
def __reduce__(self):
return (self.__class__, (self.x,))
a0 = SimpleNamespace(x=99)
a1 = MyClass1(99)
a2 = MyClass2(99)
print('* SimpleNamespace:', pickle.loads(pickle.dumps(a0))) 
print('* MyClass1:', pickle.loads(pickle.dumps(a1)))
print('* MyClass2:', pickle.loads(pickle.dumps(a2)))

相关内容

最新更新