No sé qué hacen los métodos __setstate__y __getstate__, así que ayúdame con un ejemplo simple.
python
serialization
zjm1126
fuente
fuente

Respuestas:
Aquí hay un ejemplo muy simple de Python que debería complementar los documentos de pickle .
class Foo(object): def __init__(self, val=2): self.val = val def __getstate__(self): print("I'm being pickled") self.val *= 2 return self.__dict__ def __setstate__(self, d): print("I'm being unpickled with these values: " + repr(d)) self.__dict__ = d self.val *= 3 import pickle f = Foo() f_data = pickle.dumps(f) f_new = pickle.loads(f_data)fuente
Ejemplo mínimo
De todo lo que sale
getstate, entrasetstate. No tiene por qué ser un dict.Lo que sale de
getstatedebe ser pickeable, por ejemplo, formada por muebles empotrados básicos comoint,str,list.class C(object): def __init__(self, i): self.i = i def __getstate__(self): return self.i def __setstate__(self, i): self.i = i assert pickle.loads(pickle.dumps(C(1), -1)).i == 1Defecto
__setstate__El valor predeterminado
__setstate__toma undict.self.__dict__es una buena opción como en https://stackoverflow.com/a/1939384/895245 , pero podemos construir uno nosotros mismos para ver mejor lo que está sucediendo:class C(object): def __init__(self, i): self.i = i def __getstate__(self): return {'i': self.i} assert pickle.loads(pickle.dumps(C(1), -1)).i == 1Defecto
__getstate__Análogo a
__setstate__.class C(object): def __init__(self, i): self.i = i def __setstate__(self, d): self.i = d['i'] assert pickle.loads(pickle.dumps(C(1), -1)).i == 1__slots__los objetos no tienen__dict__Si el objeto tiene
__slots__, entonces no tiene__dict__Si va a implementar ambos
getysetstate, la forma predeterminada es:class C(object): __slots__ = 'i' def __init__(self, i): self.i = i def __getsate__(self): return { slot: getattr(self, slot) for slot in self.__slots__ } def __setsate__(self, d): for slot in d: setattr(self, slot, d[slot]) assert pickle.loads(pickle.dumps(C(1), -1)).i == 1__slots__predeterminado get y set espera una tuplaSi desea reutilizar el valor predeterminado
__getstate__o__setstate__, tendrá que pasar tuplas como:class C(object): __slots__ = 'i' def __init__(self, i): self.i = i def __getsate__(self): return (None, { slot: getattr(self, slot) for slot in self.__slots__ }) assert pickle.loads(pickle.dumps(C(1), -1)).i == 1No estoy seguro para qué es esto.
Herencia
Primero vea que el decapado funciona por defecto:
class C(object): def __init__(self, i): self.i = i class D(C): def __init__(self, i, j): super(D, self).__init__(i) self.j = j d = pickle.loads(pickle.dumps(D(1, 2), -1)) assert d.i == 1 assert d.j == 2Herencia personalizada
__getstate__Sin
__slots__ella es fácil, ya que la__dict__forDcontiene la__dict__forC, por lo que no necesitamos tocarCen absoluto:class C(object): def __init__(self, i): self.i = i class D(C): def __init__(self, i, j): super(D, self).__init__(i) self.j = j def __getstate__(self): return self.__dict__ def __setstate__(self, d): self.__dict__ = d d = pickle.loads(pickle.dumps(D(1, 2), -1)) assert d.i == 1 assert d.j == 2Herencia y
__slots__Con
__slots__, necesitamos reenviar a la clase base y podemos pasar tuplas:class C(object): __slots__ = 'i' def __init__(self, i): self.i = i def __getstate__(self): return { slot: getattr(self, slot) for slot in C.__slots__ } def __setstate__(self, d): for slot in d: setattr(self, slot, d[slot]) class D(C): __slots__ = 'j' def __init__(self, i, j): super(D, self).__init__(i) self.j = j def __getstate__(self): return ( C.__getstate__(self), { slot: getattr(self, slot) for slot in self.__slots__ } ) def __setstate__(self, ds): C.__setstate__(self, ds[0]) d = ds[1] for slot in d: setattr(self, slot, d[slot]) d = pickle.loads(pickle.dumps(D(1, 2), -1)) assert d.i == 1 assert d.j == 2Lamentablemente no es posible reutilizar los predeterminados
__getstate__y__setstate__de la base: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ nos vemos obligados a definirlos.Probado en Python 2.7.12. GitHub aguas arriba .
fuente
Estos métodos se utilizan para controlar cómo el módulo de encurtidos encurtidos y despemados los objetos . Por lo general, esto se maneja automáticamente, por lo que, a menos que necesite anular la forma en que se encurtió o despejó una clase, no debería tener que preocuparse por eso.
fuente