2010-04-25 118 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