मुझे नहीं पता कि क्या __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)
न्यूनतम उदाहरण
जो भी बाहर आता है, getstate
भीतर चला जाता है setstate
। इसे डिक्टेट करने की जरूरत नहीं है।
जो कुछ भी से बाहर आता है getstate
pickeable होना चाहिए, जैसे बुनियादी बनाया-इन से बना जैसे 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 पर परीक्षण किया गया। गिटहब ऊपर ।
इन तरीकों का उपयोग यह नियंत्रित करने के लिए किया जाता है कि अचार मॉड्यूल द्वारा वस्तुओं को कैसे उठाया और अप्रकाशित किया जाता है । यह आमतौर पर स्वचालित रूप से नियंत्रित किया जाता है, इसलिए जब तक आपको ओवरराइड करने की आवश्यकता नहीं होती है कि क्लास को कैसे उठाया जाता है या अप्रकाशित किया जाता है, तो आपको इसके बारे में चिंता करने की आवश्यकता नहीं है।