考虑以下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
中)请注意,我尝试仅将self.x = x
替换为pass
,但没有任何改变。
除了通过不继承而重新实现MyClass2之外,还有其他方法可以使这项工作吗?
答案 0 :(得分:2)
问题是SimpleNamespace
定义了__reduce__
用于解开对象的pickle
。但是,__reduce__
中定义的SimpleNamespace
与您的__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)))