2011-02-17 29 views

उत्तर

96

निम्नलिखित परिस्थिति पर विचार एस __init__ छोड़ दिया गया है। इसका कारण यह है कि B का __init__A का __init__ सीधे कॉल करता है।

super का उद्देश्य विरासत हीरे को हल करना है। आप अन-टिप्पणी

# super(B,self).__init__() 

और टिप्पणी बाहर

A.__init__(self) 

तो कोड पैदावार अधिक वांछनीय परिणाम:

Running D.__init__ 
Running B.__init__ 
Running C.__init__ 
Running A.__init__ 

अब सभी __init__ पद्धतियों को बुलाया मिलता है।ध्यान दें कि उस समय जब आप B.__init__ को परिभाषित करते हैं तो आप सोच सकते हैं कि super(B,self).__init__()A.__init__(self) पर कॉल करने जैसा ही है, लेकिन आप गलत होंगे। उपर्युक्त स्थिति में, super(B,self).__init__() वास्तव में C.__init__(self) पर कॉल करता है।

पवित्र सिगरेट, B कुछ भी नहीं के बारे में C जानता है, और अभी तक super(B,self) कॉल करने के लिए C के __init__ जानता है? इसका कारण यह है कि self.__class__.mro() में C शामिल हैं। दूसरे शब्दों में, self (या उपर्युक्त में, foo) C के बारे में जानता है।

तो सावधान रहें - दोनों कवक नहीं हैं। वे काफी अलग परिणाम प्राप्त कर सकते हैं।

superhas pitfalls. का उपयोग करना विरासत आरेख में सभी वर्गों के बीच समन्वय का एक बड़ा स्तर लेता है। (वे, उदाहरण के लिए, या तो एक ही कॉल हस्ताक्षर __init__ के लिए के बाद से किसी विशेष __init__ पता नहीं है जो अन्य __init__super अगले कॉल कर सकते हैं होना चाहिए,, वरना use **kwargs ।) इसके अलावा, आप super हर जगह का उपयोग कर के बारे में अनुरूप होना चाहिए। इसे एक बार छोड़ दें (उपर्युक्त उदाहरण में) और आप super के पूरे उद्देश्य को हराते हैं। अधिक नुकसान के लिए लिंक देखें।

यदि आपके वर्ग पदानुक्रम पर पूर्ण नियंत्रण है, या आप विरासत हीरे से बचें, तो super की आवश्यकता नहीं है।

+2

+1। मैं इसे खुद पोस्ट करने वाला था। –

+0

thnx, आपने मेरी गलत धारणा को मंजूरी दे दी है। – 0xc0de

+3

[पायथन का सुपर() सुपर माना जाता है!] (Http://rhettinger.wordpress.com/2011/05/26/super-Considered-super/) दिखाता है कि क्यों और कैसे 'सुपर() 'का उपयोग करें। बीटीडब्ल्यू, नए स्टाइल क्लास और एकाधिक विरासत के साथ आम 'ऑब्जेक्ट' माता-पिता के कारण हमेशा एक विरासत हीरा होता है। – jfs

7

कोई जुर्माना के रूप में है नहीं है:

super(SuperClass, instance).method(args) 

वहाँ करने के लिए किसी भी नुकसान है , हालांकि आपका उदाहरण कुछ हद तक गुमराह है। पहले उदाहरण में, यह

super(SubClass, instance).method(args) # Sub, not SuperClass 

होना चाहिए और है कि मुझे सुराग उद्धृत करने के लिए Python docs:

super के लिए दो विशिष्ट उपयोग के मामलों रहे हैं। एक विरासत के साथ एक वर्ग पदानुक्रम में, super का उपयोग माता-पिता कक्षाओं को स्पष्ट रूप से नाम दिए बिना संदर्भित करने के लिए किया जा सकता है, इस प्रकार कोड को और अधिक बनाए रखने योग्य बना दिया जा सकता है। यह अन्य प्रोग्रामिंग भाषाओं में super के उपयोग की बारीकी से समानता का उपयोग करता है।

दूसरा उपयोग केस गतिशील निष्पादन वातावरण में सहकारी एकाधिक विरासत का समर्थन करना है। यह उपयोग केस पायथन के लिए अद्वितीय है और यह स्थिर रूप से संकलित भाषाओं या भाषाओं में नहीं मिलता है जो केवल एकल विरासत का समर्थन करते हैं। इससे "डायमंड आरेख" को कार्यान्वित करना संभव हो जाता है जहां एकाधिक आधार वर्ग एक ही विधि को लागू करते हैं। अच्छा डिज़ाइन यह निर्देश देता है कि इस विधि में प्रत्येक मामले में एक ही कॉलिंग हस्ताक्षर है (क्योंकि कॉल का क्रम रनटाइम पर निर्धारित होता है, क्योंकि वह ऑर्डर कक्षा पदानुक्रम में परिवर्तनों को स्वीकार करता है, और क्योंकि उस क्रम में स्कीलिंग कक्षाएं शामिल हो सकती हैं जो रनटाइम से पहले अज्ञात हैं)।

मूल रूप से, पहली विधि का उपयोग करके आपको एकल श्रेणी के पदानुक्रमों के लिए अपनी मूल कक्षा को हार्ड-कोड नहीं करना पड़ता है, और आप वास्तव में ऐसा नहीं कर सकते जो आप चाहते हैं (कुशलतापूर्वक/प्रभावी) एकाधिक विरासत का उपयोग करते समय दूसरी विधि।

class A(object): 
    def __init__(self): 
     print('Running A.__init__') 
     super(A,self).__init__() 
class B(A): 
    def __init__(self): 
     print('Running B.__init__')   
     # super(B,self).__init__() 
     A.__init__(self) 

class C(A): 
    def __init__(self): 
     print('Running C.__init__') 
     super(C,self).__init__() 
class D(B,C): 
    def __init__(self): 
     print('Running D.__init__') 
     super(D,self).__init__() 

foo=D() 

तो कक्षाएं एक तथाकथित विरासत हीरा फार्म:

A 
/\ 
    B C 
    \/
    D 

कोड पैदावार

Running D.__init__ 
Running B.__init__ 
Running A.__init__ 

ऐसा इसलिए है क्योंकि C बुरा है 'चल रहा है

+1

क्या मैं इसे सही समझता हूं, एकल विरासत स्थितियों में 'सुपर' का उपयोग करने के लिए कोई विपक्ष नहीं है? सुपर-हानिकारक लिंक के लिए – Wolf

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