Я не знаю , что __setstate__
и __getstate__
методы делают, так что помочь мне с простым примером.
Ответы:
Вот очень простой пример для Python, который должен дополнять документацию по 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)
Минимальный пример
Все, что выходит getstate
, входит вsetstate
. Это не обязательно должен быть диктат.
Все , что выходит из getstate
должны быть pickeable, например , из основных встроенных функций , таких как 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
По умолчанию __setstate__
По умолчанию используется __setstate__
расширение dict
.
self.__dict__
- хороший выбор, как в https://stackoverflow.com/a/1939384/895245 , но мы можем создать его сами, чтобы лучше видеть, что происходит:
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
По умолчанию __getstate__
Аналогично __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__
у объектов нет __dict__
Если у объекта есть __slots__
, значит, у него нет__dict__
Если вы собираетесь реализовать оба get
и setstate
, по умолчанию используется следующий способ:
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 и set ожидают кортеж
Если вы хотите повторно использовать значение по умолчанию __getstate__
или __setstate__
, вам придется передавать кортежи как:
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
Я не уверен, для чего это нужно.
Наследование
Сначала убедитесь, что травление работает по умолчанию:
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
Наследование обычай __getstate__
Без __slots__
этого легко, поскольку __dict__
for D
содержит __dict__
for C
, поэтому нам вообще не нужно трогать C
:
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
Наследование и __slots__
С __slots__
, нам нужно перейти к базовому классу и передать кортежи:
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
К сожалению, невозможно повторно использовать значение по умолчанию __getstate__
и __setstate__
базу: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ, мы вынуждены их определить.
Протестировано на Python 2.7.12. GitHub вверх по течению .
Эти методы используются для управления процессом маринования и освобождения объектов модулем pickle . Обычно это обрабатывается автоматически, поэтому, если вам не нужно переопределять способ маринования или выделения класса, вам не нужно об этом беспокоиться.