从 SimpleNamespace 派生的 class 上的 pickle.load 类型错误

TypeError on pickle.load with class derived from SimpleNamespace

考虑这个 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'

观察:

请注意,我尝试将 self.x = x 替换为 pass,但没有任何改变。

除了在没有继承的情况下重新实现 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)))