Saya tidak tahu apa yang dilakukan __setstate__
dan __getstate__
metode, jadi bantu saya dengan contoh sederhana.
Jawaban:
Berikut adalah contoh yang sangat sederhana untuk Python yang harus melengkapi dokumen acar .
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)
Contoh minimal
Apapun yang keluar getstate
, masuk ke dalam setstate
. Ini tidak perlu menjadi dikt.
Apa pun yang datang dari getstate
harus pickeable, misalnya terdiri dari dasar built-in seperti 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
Default __setstate__
Defaultnya __setstate__
adalah dict
.
self.__dict__
adalah pilihan yang baik seperti di https://stackoverflow.com/a/1939384/895245 , tetapi kita dapat membuatnya sendiri untuk melihat dengan lebih baik apa yang sedang terjadi:
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
Default __getstate__
Analog dengan __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__
benda tidak punya __dict__
Jika benda tersebut memiliki __slots__
, maka ia tidak memiliki__dict__
Jika Anda akan menerapkan keduanya get
dan setstate
, cara default-ishnya adalah:
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 dan set default mengharapkan tupel
Jika Anda ingin menggunakan kembali default __getstate__
atau __setstate__
, Anda harus melewatkan tupel sebagai:
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
Saya tidak yakin untuk apa ini.
Warisan
Pertama, lihat bahwa pengawetan berfungsi secara default:
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
Kebiasaan warisan __getstate__
Tanpanya __slots__
mudah, karena __dict__
for D
berisi __dict__
for C
, jadi kita tidak perlu menyentuh C
sama sekali:
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
Warisan dan __slots__
Dengan __slots__
, kita perlu meneruskan ke kelas dasar, dan dapat mengirimkan tupel di sekitar:
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
Sayangnya, tidak mungkin menggunakan kembali default __getstate__
dan __setstate__
basis: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ kami terpaksa mendefinisikannya.
Diuji pada Python 2.7.12. GitHub upstream .
Metode ini digunakan untuk mengontrol bagaimana objek diawetkan dan dilepas oleh modul acar . Ini biasanya ditangani secara otomatis, jadi kecuali Anda perlu menimpa bagaimana kelas diawetkan atau diurai, Anda tidak perlu khawatir tentang itu.