pickle:如何在包含的对象上调用 __setstate__
pickle: How to invoke __setstate__ on contained object
我有 class A。它有一个接受参数的构造函数。它使用 __getstate__
和 __setstate__
实现自定义酸洗。这很好用。
我有另一个 class, B,它包含一个 class A 的实例作为属性。 Class B 也 实现了 __getstate__
和 __setstate__
。怎么让他们两个合作保存和恢复他们的状态。
让 class B 的 __getstate__
调用 class A 很容易,但是 pickle
对此一无所知,当我尝试从 B 的 __setstate__
恢复,它不能恢复子对象,因为它还没有被实例化。
示例:
import pickle
class A:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __eq__(self, other):
return self.x == other.x and self.y == other.y and self.z == other.z
def __getstate__(self):
return self.x, self.y, self.z
def __setstate__(self, state):
self.x, self.y, self.z = state
a = A(1, 2, 3)
a_save = pickle.dumps(a)
assert a == pickle.loads(a_save)
# WORKS FINE TO HERE
class B:
def __init__(self):
self.a = A(1, 2, 3)
self.b = 4
def __getstate__(self):
# Is this correct?
return self.a.__getstate__(), self.b
def __setstate__(self, state):
return self.a.__setstate__(), self.b
def __eq__(self, other):
return self.a == other.a and self.b == other.b
b = B()
b_save = pickle.dumps(b)
# Fails in pickle.loads HERE
assert b == pickle.loads(b_save)
这会产生:
Traceback (most recent call last):
File "p.py", line 41, in <module>
assert b == pickle.loads(b_save)
File "p.py", line 33, in __setstate__
return self.a.__setstate__(), self.b
AttributeError: 'B' object has no attribute 'a'
如何将 a
重构为 A 的实例并从保存的状态恢复其原始属性值?
(请注意,这是为演示问题而创建的玩具示例。实际代码要复杂得多。)
B
不应手动调用 A
的 __getstate__
和 __setstate__
。 B
甚至不需要知道 A
有那些方法。它应该处理嵌套的 A
实例,就像 A
没有这些方法一样:
def __getstate__(self):
return (self.a, self.b)
def __setstate__(self, state):
self.a, self.b = state
我有 class A。它有一个接受参数的构造函数。它使用 __getstate__
和 __setstate__
实现自定义酸洗。这很好用。
我有另一个 class, B,它包含一个 class A 的实例作为属性。 Class B 也 实现了 __getstate__
和 __setstate__
。怎么让他们两个合作保存和恢复他们的状态。
让 class B 的 __getstate__
调用 class A 很容易,但是 pickle
对此一无所知,当我尝试从 B 的 __setstate__
恢复,它不能恢复子对象,因为它还没有被实例化。
示例:
import pickle
class A:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __eq__(self, other):
return self.x == other.x and self.y == other.y and self.z == other.z
def __getstate__(self):
return self.x, self.y, self.z
def __setstate__(self, state):
self.x, self.y, self.z = state
a = A(1, 2, 3)
a_save = pickle.dumps(a)
assert a == pickle.loads(a_save)
# WORKS FINE TO HERE
class B:
def __init__(self):
self.a = A(1, 2, 3)
self.b = 4
def __getstate__(self):
# Is this correct?
return self.a.__getstate__(), self.b
def __setstate__(self, state):
return self.a.__setstate__(), self.b
def __eq__(self, other):
return self.a == other.a and self.b == other.b
b = B()
b_save = pickle.dumps(b)
# Fails in pickle.loads HERE
assert b == pickle.loads(b_save)
这会产生:
Traceback (most recent call last):
File "p.py", line 41, in <module>
assert b == pickle.loads(b_save)
File "p.py", line 33, in __setstate__
return self.a.__setstate__(), self.b
AttributeError: 'B' object has no attribute 'a'
如何将 a
重构为 A 的实例并从保存的状态恢复其原始属性值?
(请注意,这是为演示问题而创建的玩具示例。实际代码要复杂得多。)
B
不应手动调用 A
的 __getstate__
和 __setstate__
。 B
甚至不需要知道 A
有那些方法。它应该处理嵌套的 A
实例,就像 A
没有这些方法一样:
def __getstate__(self):
return (self.a, self.b)
def __setstate__(self, state):
self.a, self.b = state