2017-07-31 53 views
7

कोड है।मैं डिफॉल्टडिक्ट का वारिस कैसे कर सकता हूं और उप-विधि विधि में अपनी प्रतिलिपि विधि का उपयोग कैसे कर सकता हूं?

Traceback (most recent call last): 
    File "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 1591, in <module> 
    globals = debugger.run(setup['file'], None, None, is_module) 
    File "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 1018, in run 
    pydev_imports.execfile(file, globals, locals) # execute the script 
    File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile 
    exec(compile(contents+"\n", file, 'exec'), glob, loc) 
    File "/Users/liu/project/scir/pytorch_test/t.py", line 14, in <module> 
    b = a.my_copy() 
    File "/Users/liu/project/scir/pytorch_test/t.py", line 8, in my_copy 
    return self.copy() 
TypeError: __init__() takes 1 positional argument but 3 were given 

मैं प्रतिलिपि विधि के वारिस के लिए कैसे है और यह भी पता नहीं है कारण है कि मैं 3 तर्क दे पता नहीं है:

from collections import defaultdict 
class A(defaultdict): 
    def __init__(self): 
    super(A, self).__init__(lambda :0) 
    self.x = 1 

    def my_copy(self): 
    return self.copy() 

if __name__ == '__main__': 
    a = defaultdict(lambda :0) 
    b = a.copy() # no error when using the base class directly 
    a = A() 
    b = a.my_copy() 

त्रुटि है।

उत्तर

7

copy पर कॉल करते समय, defaultdictdefault_factory फ़ंक्शन और डेटा को पास करने के लिए तर्क के साथ एक निर्माता को आमंत्रित करता है।

आपका कन्स्ट्रक्टर कोई तर्क नहीं लेता है, इसलिए यह केवल निश्चित फैक्ट्री के साथ खाली डिक्ट बनाने में सक्षम है।

इस तरह अपने निर्माता को ठीक करें:

def __init__(self,*args): 

लेकिन तुम माँ वर्ग या कॉपी किए गए शब्दकोश में args पारित करने के लिए खाली हो जाएगा (नहीं है कि आप चाहते हैं) है।

आप डिफ़ॉल्ट कारखाने विशेषज्ञता कर रहे हैं, आप एक विशेष मामला बनाने के लिए है, तो args खाली हैं:

class A(defaultdict): 
    def __init__(self,*args): 
    if args: 
     super(A, self).__init__(*args) 
    else: 
     super(A, self).__init__(int) # better than lambda : 0 

या हो सकता है एक त्रिगुट के साथ सरल:

class A(defaultdict): 
    def __init__(self,*args): 
    super(A, self).__init__(*(args or (int,))) 
  • जब args खाली नहीं है (copy से कहा जाता है), तो प्रतिलिपि मूल (गुण & डेटा) की गुण लेती है।
  • जब args खाली है, तो इसका मतलब है कि आप एक नया नियम बना रहे हैं, इसलिए यह केवल डिफ़ॉल्ट फैक्ट्री तर्क को ठीक करता है।

इसके अलावा: आप (lambda :0)(int) द्वारा प्रतिस्थापित कर सकते हैं।

संपादित करें: एक और अधिक जटिल तरीका है, लेकिन जो यकीन है कि (यदि पहला तर्क int नहीं है एक चेतावनी के साथ हो सकता है) कि उपयोगकर्ता डिफ़ॉल्ट बदल नहीं सकते होगा पहला तर्क और बल int अनदेखी करने के लिए बनाता है:

super(A, self).__init__(*([int]+list(args[1:]))) 

कि काम करेगा, लेकिन मुझे बहस को अनदेखा करने का विचार पसंद नहीं है।

एक निष्कर्ष के रूप में, सामान्य रूप में निर्मित प्रकार के लिए विरासत में मुश्किल है और सावधानी से किया जाना चाहिए (देखें एक और उदाहरण क्या करने की कोशिश कर रहा है कि एक pandas dataframe साथ: building a class from an existing one)। कभी-कभी defaultdict के साथ तर्क के रूप में कक्षा बनाते हैं, और जो नकल/रिले केवल उन्हीं विधियों का उपयोग करने की योजना बना रहे हैं जो कम दुष्प्रभाव पैदा करेंगे।

+0

यह उपयोगकर्ता को एक अलग कारखाना निर्दिष्ट करने देता है, जो शायद ओपी चाहता है। –

+1

@brunodesthuilliers मेरा संपादन देखें। लेकिन मेरा निष्कर्ष यह है कि: अंतर्निहित प्रकार से सुरक्षित रूप से उत्तराधिकारी होना मुश्किल है। –

2

defaultdict.__init__() तीन तर्क लेता है: self (बेशक) , an optional factory callable for missing keys and an optional set of key:values (which cand be either a dict or a sequence of (कुंजी, मूल्य) `जोड़े)।

defaultdict.copy() एक नया defaultdict उदाहरण बनाएगा और इसे factory कॉल करने योग्य और इसकी वर्तमान कुंजी की उथली प्रतिलिपि पास करेगा: मान सेट।

आपके उप-वर्ग का __init__ केवल self तर्क के रूप में लेता है, लेकिन तीन के साथ बुलाया जाता है।

ठीक यहाँ के पुनर्लेखन के लिए A.__init__ तो यह दोनों ही मामलों को संभाल सकता है:

class A(defaultdict): 
    def __init__(self, *args): 
     # make sure we force the factory 
     args = (int,) + args[1:] 
     super(A, self).__init__(*args) 
1

मैं विस्तार करने के लिए एक जवाब के लिए एक छोटी सी टिप्पणी था क्या फैसला किया। हालांकि पहले से दिए गए उत्तरों में एक संपूर्ण विश्लेषण दिया गया था, लेकिन प्रस्तावित तर्क संशोधन को नापसंद करता हूं। दोनों डिफॉल्ट डिक्ट और अंतर्निहित निर्देश में एक गैर-तुच्छ हस्ताक्षर (तर्कों का उपयोग) होता है। नीचे दिए गए कोड तर्क स्पर्श नहीं करता है और उन्हें मूल कार्यान्वयन के लिए कोई परिवर्तन नहीं गुजरता है:

def __init__(self, *args, **kwargs): 
    super(A, self).__init__(*args, **kwargs) 
    self.default_factory = int 

इसके अलावा kwargs संरक्षित कर रहे हैं, उदाहरण के लिए A(a=1,b=2) काम करता है।

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

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