2009-12-21 40 views
36

Tôi không biết phương pháp __setstate____getstate__ làm gì, vì vậy hãy giúp tôi với một ví dụ đơn giản.Ví dụ đơn giản về sử dụng __setstate__ và __getstate__

+2

-1: Bạn thậm chí có cố xem tài liệu không? – nikow

+0

tôi nhìn thấy nó, nhưng tiếng anh của tôi không phải là rất tốt, và tôi không biết rằng có nghĩa là, xin lỗi – zjm1126

+17

Các tài liệu không phải là rất tốt về điểm này anyway. –

Trả lời

33

Đây là một ví dụ rất đơn giản cho Python 2 có thể bổ sung pickle docs.

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:", d 
    self.__dict__ = d 
    self.val *= 3 

import pickle 
f = Foo() 
f_string = pickle.dumps(f) 
f_new = pickle.loads(f_string) 
4

Các phương pháp này được sử dụng để kiểm soát cách đối tượng được chọn và được giải thích bởi mô-đun pickle. Điều này thường được xử lý tự động, do đó, trừ khi bạn cần ghi đè cách thức một lớp được chọn hoặc không được nhấp chuột, bạn không cần phải lo lắng về nó.

9

dụ Minimal

Dù đi ra getstate, đi vào setstate. Nó không cần phải là một dict.

Bất kỳ nội dung nào xuất phát từ getstate phải có thể chọn, ví dụ: bao gồm các bản dựng sẵn 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__

Giá trị mặc định __setstate__ mất một dict.

self.__dict__ là một lựa chọn tốt như trong https://stackoverflow.com/a/1939384/895245, nhưng chúng ta có thể xây dựng một chính mình để thấy rõ hơn những gì đang xảy 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ự như __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__ đối tượng không có __dict__

Nếu đối tượng có __slots__, sau đó nó không có __dict__

Nếu bạn đang đi để thực hiện cả hai getsetstate, các default- ish cách 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__ mặc định được và đặt hy vọng một tuple

Nếu bạn muốn sử dụng lại các mặc định __getstate__ hoặc __setstate__, bạn sẽ phải vượt qua các bộ xung quanh 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 chắn đây là những gì cho.

Inheritance

Đầu tiên thấy rằng tẩy công trình 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 

Inheritance tùy chỉnh __getstate__

Without __slots__ nó rất dễ dàng, vì __dict__ cho D chứa __dict__ cho C, s o chúng tôi không cần phải chạm vào C tại tất 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 

Thừa kế và __slots__

Với __slots__, chúng ta cần phải chuyển tiếp đến các lớp cơ sở, và có thể vượt qua các bộ 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____setstate__ của cơ sở: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ chúng tôi buộc phải xác định nó.

Đã thử nghiệm trên Python 2.7.12. GitHub phía trên: https://github.com/cirosantilli/python-cheat/blob/master/pickle_cheat.py

Các vấn đề liên quan