2010-04-25 53 views
40

我想讓我的課實現保存和加載功能,它只是簡單地做一個類的醃菜。但顯然你不能以下面的方式使用'自我'。你怎麼能這樣做?如何醃製自己?

self = cPickle.load(f) 

    cPickle.dump(self,f,2) 
+0

我能酸洗__dict__,但隨後我將無法以後修改該類。 – Mark 2010-04-25 20:17:17

回答

31

這就是我最終做的。更新__dict__意味着我們保留所有添加到類中的新成員變量,並只更新當對象最後一次被pickle時出現的變量。看起來最簡單的方法是在類中保存保存和加載代碼,所以調用代碼只需要一個object.save()。

def load(self): 
    f = open(self.filename, 'rb') 
    tmp_dict = cPickle.load(f) 
    f.close()   

    self.__dict__.update(tmp_dict) 


def save(self): 
    f = open(self.filename, 'wb') 
    cPickle.dump(self.__dict__, f, 2) 
    f.close() 
+5

一個次要的PEP8 nitpick - 函數應該用小寫命名'load'和'save' https://www.python.org/dev/peps/pep-0008/#function-names – 2015-06-17 16:18:20

+4

@AdamMatan我會說專業... – danijar 2016-03-06 16:21:52

+0

這是一個「合併」。在調用'self .__ dict __。update(..)'之前,您應該調用'self .__ dict __。clear() – deepelement 2017-08-15 22:00:14

2

有一個如何醃製實例here, in the docs的例子。 (向下搜索「TextReader」示例)。我們的想法是定義__getstate____setstate__方法,它們允許您定義需要清理的數據以及如何使用該數據重新實例化對象。

+1

這並不能解決問題,因爲您仍然無法在類的Load函數中調用self = cPickle.load(f)以便用加載的數據填充類。 或者當然我可以醃製類數據本身,但我試圖避免編寫所有代碼,並在類成員變量更改時被迫更新它。 – Mark 2010-04-25 20:44:25

16

轉儲部分應該按照您的建議工作。對於加載部分,您可以定義從給定文件加載實例並返回它的@classmethod

@classmethod 
def loader(cls,f): 
    return cPickle.load(f) 

那麼調用者會做這樣的事情:

class_instance = ClassName.loader(f) 
+0

所以你說的是類Foo,實例foo我可以做foo.Save()但我不能做foo.Load()我將不得不做foo = foo。Load() - (可以使用實例或類名稱調用類方法) – Mark 2010-04-25 20:39:58

+4

您應該使用foo = Foo.load()而不是foo = Foo(); foo.load()。例如,如果Foo有一些必須傳遞給init的變量,則需要將它們設置爲foo = Foo()。或者如果init執行一些存儲在實例中的變量的大量計算,那就沒有用處了。 – 2010-04-25 20:52:57

+1

這有效,原來我有 foo = Foo('somefilename') 而Foo正在自己加載其數據。現在我做一個: foo = Foo.Load('somefilename') 如果我修改了Foo的定義,我仍然可以在pickle加載的foo實例中使用新的函數/成員。 – Mark 2010-04-25 21:03:29

-2

如何編寫一個名爲Serializable類將實現轉儲和裝載,並從它讓你的類繼承?

6

如果您希望您的類從已保存的泡菜更新自己......你幾乎必須使用__dict__.update,因爲你在你自己的答案都有。這有點像一隻貓追逐它的尾巴,但是......因爲你要求實例在事先狀態下基本上「重置」自己。

你的答案有一些微調。你實際上可以醃製self

>>> import dill 
>>> class Thing(object): 
... def save(self): 
...  return dill.dumps(self) 
... def load(self, obj): 
...  self.__dict__.update(dill.loads(obj).__dict__) 
... 
>>> t = Thing() 
>>> t.x = 1 
>>> _t = t.save() 
>>> t.x = 2 
>>> t.x 
2 
>>> t.load(_t) 
>>> t.x 
1 

我以前loadsdumps代替loaddump因爲我想泡菜保存到一個字符串。使用loaddump也可以。 而實際上,我可以使用dill將一個類實例浸泡到一個文件中,以備後用......即使這個類是交互式定義的。從上面繼續...

>>> with open('self.pik', 'w') as f: 
... dill.dump(t, f) 
... 
>>> 

然後停止和重新啓動...

Python 2.7.10 (default, May 25 2015, 13:16:30) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill 
>>> with open('self.pik', 'r') as f: 
... t = dill.load(f) 
... 
>>> t.x 
1 
>>> print dill.source.getsource(t.__class__) 
class Thing(object): 
    def save(self): 
    return dill.dumps(self) 
    def load(self, obj): 
    self.__dict__.update(dill.loads(obj).__dict__) 

>>> 

我使用dill,這可以在這裏找到:https://github.com/uqfoundation