source

__setstate_ 및 __getstate_의 간단한 사용 예

factcode 2023. 8. 12. 10:45
반응형

__setstate_ 및 __getstate_의 간단한 사용 예

무슨 일인지 모르겠어요__setstate__그리고.__getstate__방법은 그러하므로 간단한 예를 들어 주십시오.

여기 피클 문서를 보완해야 하는 파이썬의 매우 간단한 예가 있습니다.

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)

출력:

I'm being pickled
I'm being unpickled with these values: {'val': 4}

최소 예제

결과가 어떻든getstate에 들어갑니다.setstate받아쓰기일 필요는 없습니다.

결과가 어떻든getstate선택 가능해야 합니다. 예를 들어 다음과 같은 기본 내장형으로 구성됩니다.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
import pickle
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 __getstate__(self):
        return { slot: getattr(self, slot) for slot in self.__slots__ }
    def __setstate__(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 __getstate__(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 업스트림에서 테스트되었습니다.

이러한 방법은 피클 모듈에 의해 객체가 피클되고 제거되는 방식을 제어하는 데 사용됩니다.일반적으로 이 작업은 자동으로 처리되므로 클래스를 절이거나 절이지 않은 방법을 재정의할 필요가 없는 한 걱정할 필요가 없습니다.

@BrainCore의 답변에 대한 설명.실제로 당신은 아마도 수정하고 싶지 않을 것입니다.self안에서.__getstate__대신 새로운 개체를 구성하여 더 이상 사용할 수 있도록 원본을 변경하지 않습니다.다음은 이와 같은 내용입니다.

import pickle

class Foo:
    def __init__(self, x:int=2, y:int=3):
        self.x = x
        self.y = y
        self.z = x*y

    def __getstate__(self):
        # Create a copy of __dict__ to modify values and return;
        # you could also construct a new dict (or other object) manually
        out = self.__dict__.copy()
        out["x"] *= 3
        out["y"] *= 10
        # You can remove attributes, but note they will not get set with
        # some default value in __setstate__ automatically; you would need
        # to write a custom __setstate__ method yourself; this might be
        # useful if you have unpicklable objects that need removing, or perhaps
        # an external resource that can be reloaded in __setstate__ instead of
        # pickling inside the stream
        del out["z"]
        return out

    # The default __setstate__ will update Foo's __dict__;
    # so no need for a custom implementation here if __getstate__ returns a dict;
    # Be aware that __init__ is not called by default; Foo.__new__ gets called,
    # and the empty object is modified by __setstate__

f = Foo()
f_str = pickle.dumps(f)
f2 = pickle.loads(f_str)

print("Pre-pickle:", f.x, f.y, hasattr(f,"z"))
print("Post-pickle:", f2.x, f2.y, hasattr(f2,"z"))

언급URL : https://stackoverflow.com/questions/1939058/simple-example-of-use-of-setstate-and-getstate

반응형