2010-10-04 6 views
10

मैं एक वर्ग है कि इस तरह defaultdict से विरासत है:डिफॉल्टडिक्ट से प्राप्त होने वाली कक्षा के अचार और अनपिक उदाहरण कैसे करें?

class listdict(defaultdict): 
    def __init__(self): 
     defaultdict.__init__(self, list) 

मैं इसे अचार कर सकते हैं, लेकिन जब मैं यह unpickle, ऐसा होता है:

('__init__() takes exactly 1 argument (2 given)', <class 'listdict'>, (<type 'list'>,)) 

वर्ग के किसी विशेष तरीकों को परिभाषित नहीं करता अचार प्रोटोकॉल। एक सामान्य defaultdict(list) की पिकलिंग और अनपिक्लिंग अपेक्षा के अनुसार काम करता है। क्या कोई मुझे प्रबुद्ध कर सकता है?

+0

आप pickle' या उपयोग कर रहे हैं '' cpickle'? – aaronasterling

+0

मैं 'cpickle' का उपयोग कर रहा हूं। –

उत्तर

8

प्रकार परिभाषित करते हैं कि तरीकों के एक या अधिक (काफी बड़े) सेट को परिभाषित करके इसका उदाहरण कैसे उठाया जाता है। प्रत्येक का अपना सूक्ष्म व्यवहार होता है। the docs on the pickle protocol देखें।

>>> l = collections.defaultdict(list) 
>>> l.__reduce__() 
(<type 'collections.defaultdict'>, (<type 'list'>,), None, None, <dictionary-itemiterator object at 0x7f031fb3c470>) 

टपल में पहला आइटम वहाँ प्रकार है, और दूसरे मद जब यह instantiating प्रकार के पारित करने के लिए तर्क की टपल है: collections.defaultdict के मामले में, यह __reduce__ विधि का उपयोग करता। यदि आप __reduce__ ओवरराइड नहीं करते हैं, तो पहला आइटम सही ढंग से आपके प्रकार में बदल जाएगा, लेकिन दूसरा आइटम नहीं होगा। यह आपको दिखाई देने वाली त्रुटि का कारण बनता है। आप इसे कैसे ठीक कर सकता है की एक कच्चे उदाहरण:

>>> import collections 
>>> import pickle 
>>> class C(collections.defaultdict): 
...  def __init__(self): 
...   collections.defaultdict.__init__(self, list) 
...  def __reduce__(self): 
...   t = collections.defaultdict.__reduce__(self) 
...   return (t[0],()) + t[2:] 
... 
>>> c = C() 
>>> c[1].append(2) 
>>> c[2].append(3) 
>>> c2 = pickle.loads(pickle.dumps(c)) 
>>> c2 == c 
True 

यह केवल एक कच्चे उदाहरण है अचार (__reduce_ex__ की तरह) के लिए और अधिक और यह सब काफी जटिल है, क्योंकि है। इस मामले में, __getinitargs__ का उपयोग करना अधिक सुविधाजनक हो सकता है।

वैकल्पिक रूप से, आप कर सकते हैं अपने वर्ग के __init__ विधि एक वैकल्पिक प्रतिदेय ले, list को दोषी, या तुम सिर्फ एक वर्ग के बजाय एक समारोह इस्तेमाल कर सकते हैं:

def listdict(): 
    return collections.defaultdict(list) 
+0

धन्यवाद! मैंने डिफ़ॉल्ट पैरामीटर के लिए जाने का फैसला किया, क्योंकि यह सबसे सरल और सबसे स्थिर विकल्प प्रतीत होता था। –

+0

वास्तव में? समारोह * बहुत * सरल है :) –

+0

धन्यवाद। इससे मुझे '[0] * self._size' का उपयोग डिफ़ॉल्ट मान के रूप में करने के मुद्दे को हल करने में मदद मिली, और' _size' param पिकलिंग पर बने रहे। –

-1

वह त्रुटि इंगित करती है कि आपकी 'सूची' कक्षा से एक तर्क (अंतर्निहित स्वयं) लेने की उम्मीद थी, लेकिन दो तर्क प्राप्त हुए।

आपकी कक्षा डिफॉल्टडिक्ट से विरासत में है, और प्रारंभकर्ता को परिभाषित करती है। यह प्रारंभकर्ता डिफ़ॉल्ट डिक्टेंट के प्रारंभकर्ता को कॉल करता है और इसे 'सूची' पास करता है, जो इस मामले में या तो एक समारोह या कक्षा हो सकता है। (मुझे जांच करने के लिए परेशान नहीं किया जा सकता है)।

क्या आप शायद मतलब यह करने के लिए है:

class listdict(defaultdict): 
    def __init__(self, list): 
     defaultdict.__init__(self, list) 

अब, जब listdict एक दी गई सूची के साथ initialised है, यह उस सूची defaultdict के निर्माता के लिए, गुजरता है बल्कि वैश्विक सूची के लिए एक संदर्भ गुजर से।

(कहा जाता है कि, इसे एक ऐसे नाम का उपयोग करने के लिए बुरी शैली माना जाता है जो सामान्य वैश्विक विधियों और वर्गों जैसे 'str', 'list', आदि के समान है, क्योंकि आप उलझन में हैं)।

+1

'सूची' एक वर्ग है। ओपी एक विशेष सूची नहीं दे रहा था, लेकिन जो वर्ग, एक कॉल करने योग्य के रूप में, अपने लिए फैक्ट्री फ़ंक्शन के रूप में कार्य करता है, जो 'डिफॉल्टडिक्ट' का कन्स्ट्रक्टर तर्क के रूप में होता है। 'सूची' रखने के साथ 'सूची' को तर्क के रूप में 'डिफॉल्टडिक्ट' उप-वर्ग के उद्देश्य को हराया जाता है। – aaronasterling

+0

@Aaron इसे सही मिला है। –

+0

यह हर बार फिर से होने वाला है – aaronasterling

संबंधित मुद्दे