如何自我序列化?
我想让我的类实现保存和加载的功能,这样可以简单地把这个类的内容保存下来。但是显然在下面的写法中你不能使用'self'。那我该怎么做呢?
self = cPickle.load(f)
cPickle.dump(self,f,2)
5 个回答
9
如果你想让你的类从一个保存的pickle文件中更新自己,你基本上得用 __dict__.update
,就像你在自己的回答中提到的那样。不过,这有点像猫追自己的尾巴,因为你实际上是在让这个实例“重置”自己到之前的状态。
你的回答可以稍微调整一下。其实你可以直接对 self
进行pickle操作。
>>> 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
我使用了 loads
和 dumps
,而不是 load
和 dump
,因为我想把pickle保存为一个字符串。使用 load
和 dump
保存到文件也是可以的。实际上,我可以使用 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
31
你说的转储部分应该可以正常工作。至于加载部分,你可以定义一个@classmethod,这个方法可以从指定的文件中加载一个实例并返回它。
@classmethod
def loader(cls,f):
return cPickle.load(f)
然后调用这个方法的人可以这样做:
class_instance = ClassName.loader(f)
54
我最后做的就是这样。更新 __dict__
意味着我们可以保留我添加到类中的任何新成员变量,同时只更新在上一次保存对象时已经存在的那些变量。这看起来是最简单的做法,同时也保持了保存和加载的代码在类内部,所以调用代码只需要执行 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()