使用__slots__和pickle的奇怪行为

时间:2015-02-23 00:52:29

标签: python python-2.7

我最近遇到了插槽和泡菜的特殊问题。我已将问题隔离到以下设置:

import operator
import pickle

class BinaryOperator(object):
    __slots__ = ("a", "b")

    operator = None

    def __init__(self, a=None, b=None):
        self.a = a
        self.b = b

    def execute(self):
        return self.operator(self.a, self.b)

class Add(BinaryOperator):
    __slots__ = ()

    operator = operator.add

if __name__ == "__main__":
    # This works as intended
    add = Add(1, 1)
    assert add.execute() == 2

    # This fails:
    # Traceback (most recent call last):
    #  File "slotstest.py", line 26, in <module>
    #    assert pickle_add.execute() == 2
    #  File "slotstest.py", line 14, in execute
    #    return self.operator(self.a, self.b)
    # AttributeError: a
    pickle_add = pickle.loads(pickle.dumps(add))
    assert pickle_add.execute() == 2

    # Workaround using pickling version
    pickle_add = pickle.loads(pickle.dumps(add, -1))
    assert pickle_add.execute() == 2

这个问题不会发生在Python 3上,我认为这与新版本的pickle协议有关。

如何使Add与默认的Python 2.7版本的pickle兼容?

1 个答案:

答案 0 :(得分:1)

如果您需要支持古老的pickle协议,请在您的类中添加特殊方法来设置和恢复实例状态,例如

def __getstate__(self):
    return self.a, self.b

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