2010-04-25 10 views
40

Quiero que mi clase implemente las funciones Guardar y Cargar que simplemente hacen un escabeche de la clase. Pero aparentemente no puedes usar 'self' de la manera a continuación. ¿Cómo puedes hacer esto?¿Cómo salirse?

self = cPickle.load(f) 

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

pude conservar en vinagre el __dict__, pero luego No podría más tarde modificar la clase. – Mark

Respuesta

31

Esto es lo que terminé haciendo. La actualización de __dict__ significa que mantenemos las nuevas variables miembro que agrego a la clase y simplemente actualizo las que estaban allí cuando el objeto fue recogido por última vez. Parece el más simple mientras se mantiene el código de guardado y carga dentro de la clase misma, por lo que el código de llamada solo hace un 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

Un nitpick menor de PEP8 - las funciones deberían llamarse 'cargar' y' guardar' en minúscula https://www.python.org/dev/peps/pep-0008/#function-names –

+4

@ AdamMatan Diría mayor ... – danijar

+0

Esto es un 'merge'. Deberías llamar a 'self .__ dict __. Clear() 'antes de llamar a' self .__ dict __. Update (..)' – deepelement

2

Hay un ejemplo de cómo extraer una instancia here, in the docs. (Busque el ejemplo "TextReader"). La idea es definir los métodos __getstate__ y __setstate__, que le permiten definir qué datos se deben conservar en escabeche, y cómo usar esos datos para volver a crear instancias del objeto.

+1

Esto no resuelve el problema porque todavía no puede dentro de la llamada de la función de carga de la clase self = cPickle.load (f) para llenar la clase con los datos cargados. O por supuesto que puedo resumir los datos de la clase, pero estoy tratando de evitar escribir todo ese código y forzarme a actualizarlo cuando cambien las variables miembro de la clase. – Mark

16

La parte de volcado debe funcionar como sugirió. para la parte de carga, puede definir un @classmethod que carga una instancia de un archivo determinado y lo devuelve.

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

entonces la persona que llama haría algo como:

class_instance = ClassName.loader(f) 
+0

Entonces, lo que dices es con la clase Foo, instancia foo que puedo hacer foo.Save() pero no puedo hacer foo.Load() Tendría que hacer foo = foo.Load() - (los métodos de clase pueden invocarse con una instancia o nombre de clase) – Mark

+4

Tiene sentido que usted use foo = Foo.load(), y no foo = Foo(); foo.load(). por ejemplo, si Foo tiene algunas variables que DEBEN pasarse al init, necesitarías compensarlas por foo = Foo(); o si el init hace algunos cálculos pesados ​​de las variables almacenadas en la instancia, sería en vano. –

+1

Esto funciona, originalmente tenía foo = 'Foo' ('nombre_de_archivo') Y Foo estaba cargando sus datos por su cuenta. Ahora hago a: foo = Foo.Load ('somefilename') Si modifico la definición de Foo, aún puedo usar las nuevas funciones/miembros en la instancia de carga de pick-up foo. – Mark

-2

¿Cómo escribir una clase llamada Serializable que implementaría volcado y la carga y hacer que su clase herede de ella?

6

Si usted quiere tener la actualización automática de su clase a partir de una salmuera salvado ... que bastante tienen que utilizar __dict__.update, ya que tiene en su propia respuesta. Sin embargo, es como un gato persiguiendo su cola ... ya que le pides a la instancia que esencialmente se "reinicie" con el estado anterior.

Hay un ligero ajuste en su respuesta. En realidad puedes saltear 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 

que utilizan loads y dumps en lugar de load y dump porque quería la salmuera para salvar a una cadena. Usar load y dump en un archivo también funciona. Y, de hecho, puedo usar dill para extraer una instancia de clase en un archivo, para su uso posterior ... incluso si la clase se define interactivamente. Continuando desde arriba ...

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

continuación, detener y reiniciar ...

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__) 

>>> 

estoy usando dill, que está disponible aquí: https://github.com/uqfoundation

Cuestiones relacionadas