Je ne sais pas ce que font les méthodes __setstate__
et __getstate__
, alors aidez-moi avec un exemple simple.
python
serialization
zjm1126
la source
la source
Réponses:
Voici un exemple très simple pour Python qui devrait compléter la documentation 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)
la source
Exemple minimal
Tout ce qui sort de
getstate
, entresetstate
. Il n'est pas nécessaire que ce soit un dict.Tout ce qui vient de
getstate
doit être pickeable, par exemple composé de Encastrements de base commeint
,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
Défaut
__setstate__
La valeur par défaut
__setstate__
prend undict
.self.__dict__
est un bon choix comme dans https://stackoverflow.com/a/1939384/895245 , mais nous pouvons en construire un nous-mêmes pour mieux voir ce qui se passe: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
Défaut
__getstate__
Analogue à
__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__
les objets n'ont pas__dict__
Si l'objet a
__slots__
, alors il n'a pas__dict__
Si vous allez implémenter les deux
get
etsetstate
, la méthode par défaut est: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__
par défaut, get et set attend un tupleSi vous souhaitez réutiliser la valeur par défaut
__getstate__
ou__setstate__
, vous devrez passer des tuples comme suit: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
Je ne sais pas à quoi ça sert.
Héritage
Commencez par voir que le décapage fonctionne par défaut:
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
Héritage personnalisé
__getstate__
Sans
__slots__
c'est facile, puisque le__dict__
forD
contient le__dict__
forC
, nous n'avons donc pas besoin de toucherC
du tout: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
Héritage et
__slots__
Avec
__slots__
, nous devons transmettre à la classe de base et pouvons passer des tuples: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
Malheureusement il n'est pas possible de réutiliser les valeurs par défaut
__getstate__
et__setstate__
de la base: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ nous sommes obligés de les définir.Testé sur Python 2.7.12. GitHub en amont .
la source
Ces méthodes sont utilisées pour contrôler la façon dont les objets sont décapés et décapés par le module pickle . Ceci est généralement géré automatiquement, donc à moins que vous n'ayez besoin de remplacer la façon dont une classe est décapée ou décochée, vous ne devriez pas avoir à vous en soucier.
la source