2009-12-21 147 views
36

我不知道__setstate____getstate__方法的用法,請幫助我一個簡單的示例。使用__setstate__和__getstate__的簡單示例

+2

-1:你甚至試圖看看文檔? – nikow 2009-12-21 10:44:30

+0

我看到了,但我的英語不是很好,我不知道那是什麼意思,抱歉 – zjm1126 2009-12-22 01:38:52

+17

反正這個文檔不太好。 – 2012-10-17 19:31:06

回答

33

下面是Python 2的一個非常簡單的例子,它應該補充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:", d 
    self.__dict__ = d 
    self.val *= 3 

import pickle 
f = Foo() 
f_string = pickle.dumps(f) 
f_new = pickle.loads(f_string) 
4

這些方法用於控制pickle模塊如何醃漬和取消對象。這通常是自動處理的,所以除非你需要重寫一個類是如何被醃漬或取消的,否則你不需要擔心。

9

小例子

無論出來的getstate,進入setstate。它不需要是字典。

無論出自getstate都必須是可拍,例如,由基本內置插件組成,如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的默認 - ish方式是:

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__D包含__dict__C,s ·我們不需要觸摸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上游:https://github.com/cirosantilli/python-cheat/blob/master/pickle_cheat.py