代码之家  ›  专栏  ›  技术社区  ›  Gil Hamilton

pickle:如何在包含的对象上调用setstate

  •  0
  • Gil Hamilton  · 技术社区  · 6 年前

    我有类A。它有一个接受参数的构造函数。它使用 __getstate__ __setstate__ . 这个很好用。

    我有另一个类B,它包含一个类A的实例作为属性。B类 工具 _获取状态__ _设置状态__ . 我如何让他们两个在拯救和恢复他们的状态方面合作呢?

    有B级的很容易 _获取状态__ 打电话给A班,但是 pickle 什么都不知道,当我试图从B恢复时 _设置状态__ 无法还原子对象,因为它尚未实例化。

    例子:

    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 作为的实例并从保存的状态还原其原始属性值?

    (注意,这是一个用来演示问题的玩具示例。现实世界的代码要复杂得多。)

    1 回复  |  直到 6 年前
        1
  •  2
  •   user2357112    6 年前

    B 不应该调用 A __getstate__ __setstate__ 手动。 甚至不需要知道 有这些方法。它应该处理嵌套的 实例与 没有这些方法:

    def __getstate__(self):
        return (self.a, self.b)
    def __setstate__(self, state):
        self.a, self.b = state