[python] __setstate__ 및 __getstate__ 사용의 간단한 예

__setstate____getstate__메소드가 무엇을하는지 모르겠습니다 . 간단한 예를 들어 도와주세요.



답변

다음은 pickle 문서를 보완해야하는 매우 간단한 Python 예제입니다 .

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. dict 일 필요는 없습니다.

무엇이든 나오는 getstatepickeable해야합니다, 예를 들어 같은 기본 내장 된 기능들로 구성 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__을위한 D을 포함 __dict__위해 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 모듈 에서 개체를 피클 및 언 피클하는 방법을 제어하는 ​​데 사용됩니다 . 이것은 일반적으로 자동으로 처리되므로 클래스가 피클되거나 언 피클되는 방식을 재정의 할 필요가없는 한 걱정할 필요가 없습니다.


답변