Não sei o que os métodos __setstate__
e __getstate__
fazem, então me ajude com um exemplo simples.
python
serialization
zjm1126
fonte
fonte
Respostas:
Aqui está um exemplo muito simples para Python que deve complementar a documentação do 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)
fonte
Exemplo mínimo
O que quer que saia
getstate
, entrasetstate
. Não precisa ser um ditado.O que quer que sai
getstate
deve ser pickeable, por exemplo composta de built-ins 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
Padrão
__setstate__
O padrão
__setstate__
leva adict
.self.__dict__
é uma boa escolha como em https://stackoverflow.com/a/1939384/895245 , mas podemos construir um para ver melhor o que está acontecendo: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
Padrão
__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__
objetos não têm__dict__
Se o objeto tem
__slots__
, então ele não tem__dict__
Se você for implementar
get
esetstate
, a maneira padrão é: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__
get e set padrão esperam uma tuplaSe você quiser reutilizar o padrão
__getstate__
ou__setstate__
, terá que passar as 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
Não sei para que serve.
Herança
Primeiro, veja se a decapagem funciona por padrão:
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
Herança personalizada
__getstate__
Sem
__slots__
isso é fácil, já que o__dict__
forD
contém o__dict__
forC
, então não precisamos tocarC
em: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
Herança e
__slots__
Com
__slots__
, precisamos encaminhar para a classe base e podemos passar 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
Infelizmente não é possível reutilizar o padrão
__getstate__
e__setstate__
da base: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ somos obrigados a defini-los.Testado em Python 2.7.12. GitHub upstream .
fonte
Estes métodos são utilizados para controlar a forma como os objectos são decapados e unpickled pela salmoura módulo. Isso geralmente é feito automaticamente, então, a menos que você precise substituir a forma como uma classe é em conserva ou não, você não precisa se preocupar com isso.
fonte