Ejemplo simple de uso de __setstate__ y __getstate__

No sé qué __getstate__ métodos __setstate__ y __getstate__ , así que __getstate__ con un ejemplo simple.

Aquí hay un ejemplo muy simple para Python 2 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:", d self.__dict__ = d self.val *= 3 import pickle f = Foo() f_string = pickle.dumps(f) f_new = pickle.loads(f_string) 

Ejemplo minimo

Lo que sea que salga de getstate , entra en setstate . No necesita ser un dict.

Todo lo que salga de getstate debe ser seleccionable, por ejemplo, está compuesto de elementos básicos incorporados como int , 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 

Predeterminado __setstate__

El valor predeterminado __setstate__ toma un dict .

self.__dict__ es una buena opción como en https://stackoverflow.com/a/1939384/895245 , pero podemos construir uno 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 

Predeterminado __getstate__

Análogamente 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__ objetos no tienen __dict__

Si el objeto tiene __slots__ , entonces no tiene __dict__

Si va a implementar tanto get como setstate , 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__ defecto obtener y establecer espera una tupla

Si desea reutilizar el __getstate__ o __setstate__ predeterminado, tendrá que pasar las 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 de 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 di == 1 assert dj == 2 

Herencia personalizada __getstate__

Sin __slots__ es fácil, ya que __dict__ for D contiene __dict__ for C , por lo que no necesitamos tocar C 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 di == 1 assert dj == 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 di == 1 assert dj == 2 

Desafortunadamente, no es posible reutilizar los __getstate__ y __setstate__ predeterminados de la base: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ estamos obligados a definirlos.

Probado en Python 2.7.12. GitHub aguas arriba .

Estos métodos se utilizan para controlar la forma en que los objetos son decapados y no seleccionados por el módulo pickle . Por lo general, esto se maneja automáticamente, por lo tanto, a menos que necesite anular la forma en que se clasifica o elimina una clase, no debería preocuparse por eso.