__Setstate__ और __getstate__ के उपयोग का सरल उदाहरण


92

मुझे नहीं पता कि क्या __setstate__और __getstate__तरीके हैं, इसलिए एक सरल उदाहरण के साथ मेरी मदद करें।


25
डॉक्स वैसे भी इस बिंदु पर बहुत अच्छे नहीं हैं।
मैट लुओंगो

जवाबों:


80

यहाँ पायथन के लिए एक बहुत ही सरल उदाहरण है जो अचार के डॉक्स को पूरक करना चाहिए ।

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
इस उत्तर को पूरक करने के लिए "मैं उठा रहा हूँ" प्रिंट करता है, फिर "मैं इन मूल्यों से अप्रभावित हो रहा हूँ: {'val': 4}", और f_new.val है 12.
timidpueo

45

न्यूनतम उदाहरण

जो भी बाहर आता है, getstateभीतर चला जाता है setstate। इसे डिक्टेट करने की जरूरत नहीं है।

जो कुछ भी से बाहर आता है 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, डिफ़ॉल्ट-ish तरीका है:

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__ डिफ़ॉल्ट मिलता है और सेट एक टपल की उम्मीद है

यदि आप डिफ़ॉल्ट का पुन: उपयोग करना चाहते हैं __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 हम उन्हें परिभाषित करने के लिए मजबूर हैं।

पायथन 2.7.12 पर परीक्षण किया गया। गिटहब ऊपर


10

इन तरीकों का उपयोग यह नियंत्रित करने के लिए किया जाता है कि अचार मॉड्यूल द्वारा वस्तुओं को कैसे उठाया और अप्रकाशित किया जाता है । यह आमतौर पर स्वचालित रूप से नियंत्रित किया जाता है, इसलिए जब तक आपको ओवरराइड करने की आवश्यकता नहीं होती है कि क्लास को कैसे उठाया जाता है या अप्रकाशित किया जाता है, तो आपको इसके बारे में चिंता करने की आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.