Ich weiß nicht, was die __setstate__
und __getstate__
Methoden tun, also helfen Sie mir mit einem einfachen Beispiel.
Antworten:
Hier ist ein sehr einfaches Beispiel für Python, das die Pickle-Dokumente ergänzen sollte .
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)
Minimales Beispiel
Was auch immer herauskommt getstate
, geht hinein setstate
. Es muss kein Diktat sein.
Was auch immer kommt aus getstate
muss pickeable, zum Beispiel aus dem Grunde Einbauten wie 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
Standard __setstate__
Der Standardwert ist __setstate__
a dict
.
self.__dict__
ist eine gute Wahl wie unter https://stackoverflow.com/a/1939384/895245 , aber wir können selbst eine erstellen, um besser zu sehen, was los ist:
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
Standard __getstate__
Analog zu __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__
Objekte haben nicht __dict__
Wenn das Objekt hat __slots__
, dann hat es nicht__dict__
Wenn Sie beide get
und implementieren setstate
möchten, lautet die Standardeinstellung:
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__
Standardmäßig erwartet get and set ein Tupel
Wenn Sie die Standardeinstellung __getstate__
oder wiederverwenden möchten __setstate__
, müssen Sie Tupel wie folgt weitergeben:
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
Ich bin mir nicht sicher, wofür das ist.
Erbe
Stellen Sie zunächst sicher, dass das Beizen standardmäßig funktioniert:
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
Vererbungsgewohnheit __getstate__
Ohne __slots__
es ist einfach, da die __dict__
für D
enthält die __dict__
für C
, so dass wir berühren nicht brauchen C
überhaupt:
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
Vererbung und __slots__
Mit __slots__
müssen wir an die Basisklasse weiterleiten und können Tupel weitergeben:
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
Leider ist es nicht möglich, die Standardeinstellung __getstate__
und __setstate__
die Basis wiederzuverwenden : https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ Wir sind gezwungen, sie zu definieren.
Getestet auf Python 2.7.12. GitHub stromaufwärts .
Diese Methoden werden verwendet zur Steuerung , wie Objekte gebeizt und ungebeizt durch die Beize - Modul. Dies wird normalerweise automatisch erledigt. Wenn Sie also nicht überschreiben müssen, wie eine Klasse ausgewählt oder nicht ausgewählt wird, sollten Sie sich darüber keine Gedanken machen müssen.