Ví dụ đơn giản về việc sử dụng __setstate__ và __getstate__


88

Tôi không biết những gì __setstate____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.


25
Dù sao thì các tài liệu này cũng không tốt lắm.
Matt Luongo 17/10/12

Câu trả lời:


72

Đâ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)

9
Để bổ sung câu trả lời này, nó sẽ in "Tôi đang bị móc túi", sau đó "Tôi đang bị bỏ chọn với các giá trị sau: {'val': 4}" và f_new.val là 12.
timidpueo Ngày

41

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 getsetstate, 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____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 .


9

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ó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.