2009-04-15 18 views
100

मैं गोता अजगर में 'और वर्गों पर अध्याय में पढ़ रहा था में अधिभावी __init__ यह इस उदाहरण देता है:विरासत और अजगर

class FileInfo(UserDict): 
    "store file metadata" 
    def __init__(self, filename=None): 
     UserDict.__init__(self) 
     self["name"] = filename 

लेखक तो कहता है कि आप __init__ विधि ओवरराइड करना चाहते हैं, तो आप सही पैरामीटर के साथ माता-पिता __init__ को स्पष्ट रूप से कॉल करना होगा।

  1. क्या होगा यदि FileInfo कक्षा में एक से अधिक पूर्वजों की कक्षा थी?
    • क्या मुझे सभी पूर्वजों के वर्गों को __init__ विधियों को स्पष्ट रूप से कॉल करना होगा?
  2. साथ ही, क्या मुझे इसे किसी अन्य विधि से करना है जिसे मैं ओवरराइड करना चाहता हूं?
+3

ध्यान दें कि ओवरलोडिंग ओवरराइडिंग से एक अलग अवधारणा है। –

+2

हाँ, इसे ठीक करने के लिए धन्यवाद –

उत्तर

129

पुस्तक सबक्लास-सुपरक्लास कॉलिंग के संबंध में थोड़ा सा दिनांकित है। यह सबक्लास निर्मित कक्षाओं के संबंध में थोड़ा दिनांकित है।

ऐसा आजकल ऐसा लगता है।

class FileInfo(dict): 
    """store file metadata""" 
    def __init__(self, filename=None): 
     super(FileInfo, self).__init__() 
     self["name"] = filename 

निम्नलिखित नोट करें।

  1. हम सीधे बिल्ट-इन कक्षाओं उपवर्ग कर सकते हैं, dict, list, tuple, आदि

  2. तरह super समारोह इस वर्ग के सुपर-क्लास पर नज़र रखने और उचित रूप से उन में कार्यों बुला हैंडल।

+4

क्या मुझे बेहतर पुस्तक/ट्यूटोरियल की तलाश करनी चाहिए? –

+1

तो एकाधिक विरासत के मामले में, सुपर() उन्हें आपकी तरफ से नीचे ट्रैक करता है? – Dana

+2

dict के साथ क्या गलत है .__ init __(), बिल्कुल? –

3

यदि फ़ाइलइन्फो क्लास में एक से अधिक पूर्वजों की कक्षा है तो आपको निश्चित रूप से अपने सभी __init __() फ़ंक्शंस को कॉल करना चाहिए। आपको __del __() फ़ंक्शन के लिए भी ऐसा ही करना चाहिए, जो एक विनाशक है।

2

हां, आपको प्रत्येक पेरेंट क्लास के लिए __init__ पर कॉल करना होगा। यदि आप दोनों माता-पिता में मौजूद एक फ़ंक्शन को ओवरराइड कर रहे हैं, तो यह वही कार्यों के लिए जाता है।

10

आप है आधार वर्ग (ते) के __init__ तरीकों कॉल करने के लिए वास्तव में नहीं करते हैं, लेकिन आप आमतौर पर चाहते हैं कि उसे क्या करना है क्योंकि आधार वर्ग वहाँ कुछ महत्वपूर्ण initializations कि के बाकी के लिए आवश्यक हैं क्या करेंगे काम करने के लिए कक्षा के तरीके।

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

+4

तकनीकी पूर्णता के लिए, थ्रेडिंग जैसे कुछ वर्ग, थ्रेड, अगर आप कभी माता-पिता के __init__ को कॉल करने से बचने का प्रयास करते हैं तो भारी त्रुटियां फेंक देंगे। –

+5

मुझे यह सब मिल गया है "आपको बेस के कन्स्ट्रक्टर को कॉल करने की ज़रूरत नहीं है" बेहद परेशान बात करते हैं। आपको इसे किसी भी भाषा में कॉल करने की ज़रूरत नहीं है। वे सभी सदस्यों को शुरू नहीं करके, वैसे ही खराब हो जाएंगे (या नहीं)। आधार वर्गों को शुरू करने के लिए सुझाव देना बहुत से तरीकों से गलत है। यदि किसी वर्ग को प्रारंभिकरण की आवश्यकता नहीं है तो उसे भविष्य में इसकी आवश्यकता होगी। कन्स्ट्रक्टर कक्षा संरचना/भाषा निर्माण के इंटरफ़ेस का हिस्सा है, और इसका उपयोग सही ढंग से किया जाना चाहिए। इसका सही उपयोग यह है कि इसे अपने व्युत्पन्न कन्स्ट्रक्टर में कभी-कभी कॉल करें। तो इसे करो। – AndreasT

17

प्रत्येक वर्ग में जिसकी आपको विरासत की आवश्यकता है, आप प्रत्येक वर्ग का एक लूप चला सकते हैं जिसे बाल वर्ग की शुरुआत के बाद init'd की आवश्यकता होती है ... एक उदाहरण जो कॉपी किया जा सकता है बेहतर समझा जा सकता है ...

class Female_Grandparent: 
    def __init__(self): 
     self.grandma_name = 'Grandma' 

class Male_Grandparent: 
    def __init__(self): 
     self.grandpa_name = 'Grandpa' 

class Parent(Female_Grandparent, Male_Grandparent): 
    def __init__(self): 
     Female_Grandparent.__init__(self) 
     Male_Grandparent.__init__(self) 

     self.parent_name = 'Parent Class' 

class Child(Parent): 
    def __init__(self): 
     Parent.__init__(self) 
#---------------------------------------------------------------------------------------# 
     for cls in Parent.__bases__: # This block grabs the classes of the child 
      cls.__init__(self)  # class (which is named 'Parent' in this case), 
            # and iterates through them, initiating each one. 
            # The result is that each parent, of each child, 
            # is automatically handled upon initiation of the 
            # dependent class. WOOT WOOT! :D 
#---------------------------------------------------------------------------------------# 



g = Female_Grandparent() 
print g.grandma_name 

p = Parent() 
print p.grandma_name 

child = Child() 

print child.grandma_name 
+1

ऐसा लगता है कि 'Child .__ init__' में लूप के लिए आवश्यक नहीं है। जब मैं इसे उदाहरण से हटा देता हूं तो बच्चा अभी भी "दादी" प्रिंट करता है। 'माता-पिता' वर्ग द्वारा दादा दादी माता-पिता नहीं है? – Adam

+2

मुझे लगता है कि ग्रैनपेरेंट्स इनिट का पहले से ही माता-पिता के इनिट द्वारा संभाला जाता है, है ना? – johk95

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