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
getstate
debe 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 == 1
Defecto
__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 == 1
Defecto
__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
get
ysetstate
, 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 == 1
No 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 == 2
Herencia personalizada
__getstate__
Sin
__slots__
ella es fácil, ya que la__dict__
forD
contiene la__dict__
forC
, por lo que no necesitamos tocarC
en 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 == 2
Herencia 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 == 2
Lamentablemente 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