Как мариновать себя? - PullRequest
53 голосов
/ 26 апреля 2010

Я хочу, чтобы в моем классе были реализованы функции сохранения и загрузки, которые просто делают рассол класса. Но, очевидно, вы не можете использовать «я» в моде ниже. Как ты можешь это сделать?

self = cPickle.load(f)

cPickle.dump(self,f,2)

Ответы [ 5 ]

41 голосов
/ 16 мая 2010

Я так и сделал. Обновление __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()
20 голосов
/ 26 апреля 2010

Часть дампа должна работать как вы предложили. для загружаемой части вы можете определить @ classmethod , который загружает экземпляр из заданного файла и возвращает его.

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

тогда вызывающий будет делать что-то вроде:

class_instance = ClassName.loader(f)
8 голосов
/ 05 августа 2014

Если вы хотите, чтобы ваш класс обновлялся из сохраненного рассола ... вам, скорее всего, придется использовать __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

Я использовал loads и dumps вместо load и dump, потому что я хотел, чтобы соленье сохранялось в строку. Использование 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

2 голосов
/ 26 апреля 2010

Вот пример того, как выбрать экземпляр здесь, в документах . (Поиск вниз для примера "TextReader"). Идея состоит в том, чтобы определить методы __getstate__ и __setstate__, которые позволят вам определить, какие данные необходимо выбрать и как использовать эти данные для повторной обработки объекта.

0 голосов
/ 26 апреля 2010

Как насчет написания класса с именем Serializable, который будет реализовывать dump и load и заставлять ваш класс наследовать от него?

...