python - 带有派生自 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
)
请注意,我尝试用self.x = x
just替换pass
,但这并没有改变任何东西。
除了在没有继承的情况下重新实现 MyClass2 之外,还有其他方法可以完成这项工作吗?
解决方案
问题是它SimpleNamespace
定义了一个__reduce__
用来pickle
解开你的对象的。但是,__reduce__
定义的 inSimpleNamespace
与您的__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)))
推荐阅读
- linux-kernel - 在设备树中设置 GPIO bank 编号
- java - 用流替换 for 循环以添加正确和错误拼写的单词
- json - 如何获取 Kubernetes 对象的 OpenAPI 规范
- php - 在 symfony 2.8 上部署项目时出错
- sql - 奇怪的访问查询问题 - 运行保存的访问查询找不到字段。这是缓冲区问题吗?
- python - 如何限制 python 模块安装在特定版本的 Python 中?
- node.js - 批量检索 AWS ssm 参数
- python - 通过 WXnotebook 中的选项卡自动切换
- algorithm - 算法的“数学/经验验证”是什么意思?
- amazon-web-services - Cognito 组的 IAM 策略变量