2010-05-27 53 views
7

當這個對象通過它的一個屬性引用自己時,什麼是從帶有插槽的類中pickle一個對象的正確方法?下面是一個簡單的例子,我目前的實現,我不知道是100%正確的:如何使用自引用和帶有插槽的類來醃製和取消對象?

import weakref 
import pickle 

class my_class(object): 

    __slots__ = ('an_int', 'ref_to_self', '__weakref__') 

    def __init__(self): 
     self.an_int = 42 
     self.ref_to_self = weakref.WeakKeyDictionary({self: 1}) 

    # How to best write __getstate__ and __setstate__? 
    def __getstate__(self): 

     obj_slot_values = dict((k, getattr(self, k)) for k in self.__slots__) 
     # Conversion to a usual dictionary: 
     obj_slot_values['ref_to_self'] = dict(obj_slot_values['ref_to_self']) 
     # Unpicklable weakref object: 
     del obj_slot_values['__weakref__'] 
     return obj_slot_values 

    def __setstate__(self, data_dict): 
     # print data_dict 
     for (name, value) in data_dict.iteritems(): 
      setattr(self, name, value) 
     # Conversion of the dict back to a WeakKeyDictionary: 
     self.ref_to_self = weakref.WeakKeyDictionary(
      self.ref_to_self.iteritems()) 

這例如可以與測試:

def test_pickling(obj): 
    "Pickles obj and unpickles it. Returns the unpickled object" 

    obj_pickled = pickle.dumps(obj) 
    obj_unpickled = pickle.loads(obj_pickled) 

    # Self-references should be kept: 
    print "OK?", obj_unpickled == obj_unpickled.ref_to_self.keys()[0] 
    print "OK?", isinstance(obj_unpickled.ref_to_self, 
          weakref.WeakKeyDictionary) 

    return obj_unpickled 

if __name__ == '__main__': 
    obj = my_class() 
    obj_unpickled = test_pickling(obj) 
    obj_unpickled2 = test_pickling(obj_unpickled) 

這是一個正確的/健壯實施?如果my_class繼承自__slots__的類,應如何編寫__getstate____setstate____setstate__由於「循環」字典有內存泄漏嗎?

有在PEP 307了一句話,讓我懷疑是否酸洗my_class對象是一個穩健的方式在所有可能的:

__getstate__方法應返回表示對象的狀態picklable值,而不參照對象本身。

這是否與對象本身的引用被醃漬的事實相沖突?

這是很多問題:任何評論,評論或建議將不勝感激!

+1

如果您希望my_class是可分類的,請確保將self .__ slots__替換爲類似於:slots = set();對於cls in self .__ class __。mro():slots.update(getattr(cls,'__slots__',())) – 2015-08-22 00:57:10

+1

關閉我的頭頂,我會說這個子類更新'self .__ slots__',所以我猜子類化實際上沒有問題,對吧? – EOL 2015-08-22 01:08:35

+0

不是。他們沒有。 :-)想象出來需要一些時間,因此評論。 :-) – 2015-08-22 01:23:52

回答

5

它看起來像原來的帖子建議工作得很好。

至於什麼PEP 307讀取:

的__getstate__方法應返回表示對象的狀態picklable值,而不參照對象本身。

據我所知,它只意味着__getstate__方法只是返回一個不指向(不可打開)原始對象的表示。因此,只要沒有引用原始(不可打開)的對象,就返回一個引用自身的對象就沒問題了。