2013-01-07 34 views
33

पर कॉल करने के लिए कौन सा सुपर() चुनना, मैं किस माता-पिता को कॉल करने का तरीका चुनूं? मान लें कि मैं पैरेंट एएसडीएफ 2 की __init__ विधि को कॉल करना चाहता हूं। ऐसा लगता है कि मुझे सुपर() .. में ASDF1 निर्दिष्ट करना है? और अगर मैं एएसडीएफ 3 के __init__ पर कॉल करना चाहता हूं, तो मुझे ASDF2 निर्दिष्ट करना होगा?पायथन की एकाधिक विरासत: पाइथन में

>>> class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     super(ASDF1, self).__init__() 


>>> ASDF() 
ASDF2's __init__ happened 
>>> class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     super(ASDF2, self).__init__() 


>>> ASDF() 
ASDF3's __init__ happened 

मुझे बोनर लगता है। मैं क्या गलत कर रहा हूं?

उत्तर

47

यह नहीं है कि super() है। सुपर मूल रूप से एक विशिष्ट क्रम में अपने माता-पिता के एक (या सभी) को चुनता है। आप केवल एक ही माता-पिता की विधि कॉल करना चाहते हैं, इस

class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     ASDF2.__init__(self) 
10

super कॉल विधि संकल्प क्रम में अगली विधि से करते हैं। एक रैखिक विरासत पेड़ में, यह तुरंत माता-पिता वर्ग से विधि होगी।

यहां, आपके पास तीन माता-पिता हैं, और ASDF1 के परिप्रेक्ष्य से __init__ विधि ASDF2 है। आम तौर पर, सुरक्षित काम करना विरासत सूची में प्रथम श्रेणी को super तक पास करना है जबतक कि आप नहीं जानते कि आप कुछ और क्यों करना चाहते हैं।

यह सब कुछ आपको कॉल करने के लिए __init__ विधियों को स्पष्ट रूप से चुनने से छुटकारा दिलाता है। यहां सवाल यह है कि आप सभी सुपरक्लास __init__ विधियों को क्यों नहीं कॉल करना चाहते हैं।

पायथन में super के उपयोग पर काफी पर्याप्त साहित्य है, और मैं अनुशंसा करता हूं कि आप विषय को Google पर क्लिक करें और परिणाम क्या पढ़ें।

4

आप सुपर() के पहले तर्क के रूप में ASDF1 (आपके मूल वर्गों में से एक) को पास कर रहे हैं। ऐसा मत करो। इसके बजाय, आपको एएसडीएफ को सुपर() के पहले तर्क के रूप में पास करना चाहिए।

Python 2.7 documentation for super()

अजगर 2.7 डॉक्स के शब्दों में, एक ठेठ सुपर क्लास कॉल इस तरह दिखता है: करने के लिए

class C(B): 
    def method(self, arg): 
     super(C, self).method(arg) 

सूचना है कि पहला तर्क सुपर यहां सी है, जो वर्तमान वर्ग है। सुपर() को बी (पैरेंट क्लास) पास न करें।

विधि समाधान आदेश (एमआरओ) सुपर निर्धारित करने वाले वर्ग को अपने पहले तर्क के रूप में पारित कक्षा को छोड़ देता है, और उस वर्ग के माता-पिता और भाई-बहनों को देखना शुरू कर देता है। इसलिए, जब आपने एएसडीएफ 1 को सुपर() के पहले तर्क के रूप में पारित किया, तो यह एएसडीएफ 1 पर छोड़ दिया और एएसडीएफ 2 के साथ अपनी खोज शुरू की। यही कारण है कि एएसडीएफ 2 के __init__ को बुलाया गया था।


पायथन 3 में, आपको वर्तमान कक्षा को और पास नहीं करना है।

class C(B): 
    def method(self, arg): 
     super().method(arg) # This does the same thing as: 
           # super(C, self).method(arg) 
           # (Python 3 only)