82

我希望我的班级实现保存和加载功能,这些功能只需对班级进行泡菜。但显然你不能以下面的方式使用'self'。你怎么能做到这一点?

self = cPickle.load(f)

cPickle.dump(self,f,2)
4

5 回答 5

49

这就是我最终做的。更新__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()
于 2010-05-16T06:01:54.677 回答
27

转储部分应该按照您的建议工作。对于加载部分,您可以定义一个@classmethod从给定文件加载实例并返回它。

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

然后调用者会做类似的事情:

class_instance = ClassName.loader(f)
于 2010-04-25T20:29:12.583 回答
8

如果您想让您的班级从保存的泡菜中自行更新……您几乎必须使用__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

我使用loadsanddumps而不是loadanddump因为我希望泡菜保存到字符串中。对文件使用loadanddump也可以。而且,实际上,我可以用来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

于 2014-08-04T21:54:40.883 回答
3

我就是这样做的。优点是您不需要创建新对象。您可以直接加载它。

def save(self):
    with open(self.filename, 'wb') as f:
        pickle.dump(self, f)

@classmethod
def load(cls, filename):
    with open(filename, 'rb') as f:
        return pickle.load(f)

如何使用它:

class_object.save()
filename = class_object.filename
del class_object

class_object = ClassName.load(filename)

贝娄,我用一个完整的最小示例更新了答案。这可以根据您自己的需要进行调整。

import pickle

class Test:

    def __init__(self, something, filename) -> None:
        self.something = something
        self.filename = filename


    def do_something(self) -> None:
        print(id(self))
        print(self.something)

    def save(self):
        with open(self.filename, 'wb') as f:
            pickle.dump(self, f)


    @classmethod
    def load(cls, filename):
        with open(filename, 'rb') as f:
            return pickle.load(f)


test_object = Test(44, "test.pkl")
test_object.do_something()
test_object.save()
filename = test_object.filename
del test_object

recovered_object = Test.load(filename)
recovered_object.do_something()
于 2020-09-24T11:41:24.647 回答
2

在 docs 中有一个如何在此处腌制实例的示例。(向下搜索“TextReader”示例)。这个想法是定义__getstate____setstate__方法,它允许您定义需要腌制哪些数据,以及如何使用该数据重新实例化对象。

于 2010-04-25T20:24:31.097 回答