Nie wiem, co __setstate__
i __getstate__
metody nie, tak mi pomóc z prostym przykładzie.
python
serialization
zjm1126
źródło
źródło
Odpowiedzi:
Oto bardzo prosty przykład dla Pythona, który powinien uzupełniać dokumentację 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)
źródło
Minimalny przykład
Cokolwiek wychodzi
getstate
, wchodzi wsetstate
. Nie musi to być dyktando.Cokolwiek wyjdzie
getstate
musi być pickeable np składa się z podstawowych wbudowanych wtyczek takich jakint
,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
Domyślna
__setstate__
Domyślnie
__setstate__
zajmujedict
.self.__dict__
to dobry wybór, jak na https://stackoverflow.com/a/1939384/895245 , ale możemy sami zbudować taki, aby lepiej widzieć, co się dzieje: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
Domyślna
__getstate__
Analogicznie do
__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__
obiekty nie mają__dict__
Jeśli obiekt ma
__slots__
, to nie ma__dict__
Jeśli zamierzasz zaimplementować oba
get
isetstate
, domyślnym sposobem jest: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__
Domyślnie get and set oczekuje krotkiJeśli chcesz ponownie użyć domyślnego
__getstate__
lub__setstate__
, będziesz musiał przekazać krotki jako: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
Nie jestem pewien, do czego to służy.
Dziedzictwo
Najpierw zobacz, że wytrawianie działa domyślnie:
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
Niestandardowe dziedziczenie
__getstate__
Bez
__slots__
tego jest to łatwe, ponieważ__dict__
forD
zawiera__dict__
forC
, więc nie musimyC
w ogóle dotykać :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
Dziedziczenie i
__slots__
W programie
__slots__
musimy przekazać do klasy bazowej i możemy przekazywać krotki wokół: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
Niestety nie jest możliwe ponowne użycie wartości domyślnych
__getstate__
i__setstate__
bazy: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ jesteśmy zmuszeni je zdefiniować.Przetestowano w Pythonie 2.7.12. GitHub upstream .
źródło
Te metody są używane do kontrolowania sposobu wytrawiania i odblokowywania przedmiotów przez moduł marynowania . Zwykle jest to obsługiwane automatycznie, więc nie musisz się tym martwić, chyba że musisz zmienić sposób, w jaki klasa jest marynowana lub odmładzana.
źródło