Tôi không biết những gì __setstate__và __getstate__các phương pháp làm, vì vậy hãy giúp tôi với một ví dụ đơn giản.
Câu trả lời:
Đây là một ví dụ rất đơn giản cho Python sẽ bổ sung cho các tài liệu dưa chua .
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)
Ví dụ tối thiểu
Bất cứ điều gì đi ra getstate, đi vào setstate. Nó không cần phải là một chính tả.
Dù đi ra getstatephải pickeable, ví dụ như tạo thành từ các built-in cơ bản như 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
Mặc định __setstate__
Mặc định __setstate__có a dict.
self.__dict__là một lựa chọn tốt như trong https://stackoverflow.com/a/1939384/895245 , nhưng chúng tôi có thể tự xây dựng một lựa chọn để xem rõ hơn những gì đang diễn ra:
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
Mặc định __getstate__
Tương tự với __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__ đồ vật không có __dict__
Nếu đối tượng có __slots__, thì nó không có__dict__
Nếu bạn định triển khai cả hai getvà setstate, cách mặc định là:
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__ lấy và đặt mặc định mong đợi một tuple
Nếu bạn muốn sử dụng lại mặc định __getstate__hoặc __setstate__, bạn sẽ phải chuyển các bộ giá trị như:
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
Tôi không chắc cái này dùng để làm gì.
Di sản
Trước tiên, hãy thấy rằng quá trình tẩy rửa hoạt động theo mặc định:
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
Phong tục thừa kế __getstate__
Không có __slots__nó thì thật dễ dàng, vì __dict__for Dchứa __dict__for C, vì vậy chúng ta không cần phải chạm Cvào:
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
Kế thừa và __slots__
Với __slots__, chúng ta cần chuyển tiếp đến lớp cơ sở và có thể chuyển các bộ giá trị xung quanh:
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
Rất tiếc, không thể sử dụng lại mặc định __getstate__và __setstate__cơ sở: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ, chúng tôi buộc phải xác định chúng.
Đã thử nghiệm trên Python 2.7.12. GitHub ngược dòng .
Các phương pháp này được sử dụng để kiểm soát cách các đối tượng được chọn và bỏ chọn bởi mô-đun pickle . Điều này thường được xử lý tự động, vì vậy trừ khi bạn cần ghi đè lên cách một lớp được chọn hoặc bỏ chọn, bạn không cần phải lo lắng về nó.