使用__setstate__和__getstate__的简单示例


Answers:


72

这是一个非常简单的Python示例,应该补充pickle docs

class Foo(object):
  def __init__(self, val=2):
     self.val = val
  def __getstate__(self):
     print("I'm being pickled")
     self.val *= 2
     return self.__dict__
  def __setstate__(self, d):
     print("I'm being unpickled with these values: " + repr(d))
     self.__dict__ = d
     self.val *= 3

import pickle
f = Foo()
f_data = pickle.dumps(f)
f_new = pickle.loads(f_data)

9
为了补充此答案,它会显示“我正在被腌制”,然后显示“我正在被这些值腌制:{'val':4}”,并且f_new.val为
12。– timidpueo

41

最小的例子

不管发生什么getstate,都会进入setstate。它不一定是命令。

无论发生什么事的出来getstate一定是pickeable,如基本的内置插件等组成intstrlist

class C(object):
    def __init__(self, i):
        self.i = i
    def __getstate__(self):
        return self.i
    def __setstate__(self, i):
        self.i = i
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1

默认 __setstate__

默认__setstate__值为dict

self.__dict__就像https://stackoverflow.com/a/1939384/895245一样,是一个不错的选择,但是我们可以自己构造一个以更好地了解发生了什么:

class C(object):
    def __init__(self, i):
        self.i = i
    def __getstate__(self):
        return {'i': self.i}
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1

默认 __getstate__

类似于__setstate__

class C(object):
    def __init__(self, i):
        self.i = i
    def __setstate__(self, d):
        self.i = d['i']
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1

__slots__ 对象没有 __dict__

如果对象具有__slots__,则它不具有__dict__

如果要同时实现getsetstate,则默认为:

class C(object):
    __slots__ = 'i'
    def __init__(self, i):
        self.i = i
    def __getsate__(self):
        return { slot: getattr(self, slot) for slot in self.__slots__ }
    def __setsate__(self, d):
        for slot in d:
            setattr(self, slot, d[slot])
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1

__slots__ 默认获取并设置期望元组

如果要重用默认值__getstate____setstate__,则必须将元组传递为:

class C(object):
    __slots__ = 'i'
    def __init__(self, i):
        self.i = i
    def __getsate__(self):
        return (None, { slot: getattr(self, slot) for slot in self.__slots__ })
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1

我不确定这是干什么的。

遗产

首先看到默认情况下,酸洗有效:

class C(object):
    def __init__(self, i):
        self.i = i
class D(C):
    def __init__(self, i, j):
        super(D, self).__init__(i)
        self.j = j
d = pickle.loads(pickle.dumps(D(1, 2), -1))
assert d.i == 1
assert d.j == 2

继承风俗 __getstate__

没有__slots__它很容易,因为__dict__forD包含__dict__for C,所以我们根本不需要触摸C

class C(object):
    def __init__(self, i):
        self.i = i
class D(C):
    def __init__(self, i, j):
        super(D, self).__init__(i)
        self.j = j
    def __getstate__(self):
        return self.__dict__
    def __setstate__(self, d):
        self.__dict__ = d
d = pickle.loads(pickle.dumps(D(1, 2), -1))
assert d.i == 1
assert d.j == 2

继承与 __slots__

使用__slots__,我们需要转到基类,并且可以将元组传递给周围:

class C(object):
    __slots__ = 'i'
    def __init__(self, i):
        self.i = i
    def __getstate__(self):
        return { slot: getattr(self, slot) for slot in C.__slots__ }
    def __setstate__(self, d):
        for slot in d:
            setattr(self, slot, d[slot])

class D(C):
    __slots__ = 'j'
    def __init__(self, i, j):
        super(D, self).__init__(i)
        self.j = j
    def __getstate__(self):
        return (
            C.__getstate__(self),
            { slot: getattr(self, slot) for slot in self.__slots__ }
        )
    def __setstate__(self, ds):
        C.__setstate__(self, ds[0])
        d = ds[1]
        for slot in d:
            setattr(self, slot, d[slot])

d = pickle.loads(pickle.dumps(D(1, 2), -1))
assert d.i == 1
assert d.j == 2

不幸的是,无法重用默认值__getstate____setstate__基本值:https : //groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ我们被迫定义它们。

在Python 2.7.12上测试。GitHub上游


9

这些方法用于控制咸菜模块如何腌制和释放物体。这通常是自动处理的,因此除非您需要重写对类进行酸洗或酸洗的方法,否则您不必担心。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.