__Setstate__ ve __getstate__ kullanımının basit bir örneği


92

Ben ne olduğunu bilmiyorum __setstate__ve __getstate__yöntemleri, bu yüzden basit bir örnekle bana yardım yoktur.


25
Doktorlar zaten bu noktada pek iyi değil.
Matt Luongo

Yanıtlar:


80

İşte turşu belgelerini tamamlaması gereken Python için çok basit bir örnek .

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
Bu yanıtı tamamlamak için "Turşu yapılıyorum", ardından "Şu değerlerle çözülüyorum: {'val': 4}" ve f_new.val 12'dir.
timidpueo

45

Minimal örnek

Ne getstateçıkarsa çıksın içeri girer setstate. Dikte olmasına gerek yok.

Ne olursa olsun çıkan getstatepickeable olmalı, örneğin gibi temel yerleşik ins oluşan 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

Varsayılan __setstate__

Varsayılan __setstate__, bir dict.

self.__dict__https://stackoverflow.com/a/1939384/895245'te olduğu gibi iyi bir seçimdir , ancak neler olup bittiğini daha iyi görmek için kendimiz bir tane oluşturabiliriz:

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

Varsayılan __getstate__

Benzer __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__ nesneler yok __dict__

Nesne varsa __slots__, o zaman__dict__

Her ikisini de uygulayacaksanız getve setstatevarsayılan-ish yolu şudur:

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__ varsayılan get ve set bir demet bekliyor

Varsayılanı yeniden kullanmak isterseniz __getstate__veya aşağıdaki __setstate__gibi tupl'leri geçirmeniz gerekecektir:

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

Bunun ne için olduğundan emin değilim.

Miras

Öncelikle, dekapajın varsayılan olarak çalıştığını görün:

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

Kalıtım özel __getstate__

Olmadan __slots__bu yana, kolay __dict__için Diçerdiği __dict__için Cbiz dokunmak gerek kalmaz, Chiç:

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

Miras ve __slots__

İle __slots__, temel sınıfa ilerlemeliyiz ve etrafta tupl'leri geçirebiliriz:

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

Maalesef varsayılanı __getstate__ve __setstate__tabanı yeniden kullanmak mümkün değil : https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQ Bunları tanımlamak zorunda kalıyoruz.

Python 2.7.12'de test edilmiştir. GitHub yukarı akış .


10

Bu yöntemler, nesnelerin turşu modülü tarafından nasıl turşu ve söküldüğünü kontrol etmek için kullanılır . Bu genellikle otomatik olarak ele alınır, bu nedenle bir sınıfın nasıl turşulduğunu veya çözüldüğünü geçersiz kılmanız gerekmediği sürece endişelenmenize gerek yoktur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.