2011-08-21 27 views
10

में पायथन सुपर फ़ंक्शन का उपयोग यहां एक django ट्यूटोरियल में कुछ कोड है जो मैं जा रहा हूं। मैंने कभी भी पाइथन में सुपर फ़ंक्शन में कभी नहीं देखा है और जिस तरह से इसका उपयोग किया गया है, वह ऑनलाइन उदाहरणों से अलग है। यानी, आमतौर पर जब आप सुपर का उपयोग करते हैं, तो क्या आपके पास एकाधिक कक्षाएं नहीं हैं? यह आखिरी पंक्ति में है: super(Snippet, self).save(force_insert, force_update) क्या आप समझ सकते हैं कि वहां क्या हो रहा है और इसे लिखने का एक वैकल्पिक तरीका क्या होगा। ऐसा लगता है कि सहेजने की विधि खुद को यहां बुला रही है?django मॉडल

class Snippet(models.Model): 
    title = models.CharField(max_length=255) 
    language = models.ForeignKey(Language) 
    author = models.ForeignKey(User) 
    description = models.TextField() 
    description_html = models.TextField(editable=False) 
    code = models.TextField() 
    highlighted_code = models.TextField(editable=False) 
    tags = TagField() 
    pub_date = models.DateTimeField(editable=False) 
    updated_date = models.DateTimeField(editable=False) 

    class Meta: 
     ordering = ['-pub_date'] 

    def __unicode__(self): 
     return self.title 

    def save(self, force_insert=False, force_update=False): 
     if not self.id: 
      self.pub_date = datetime.datetime.now() 
     self.updated_date = datetime.datetime.now() 
     self.description_html = markdown(self.description) 
     self.highlighted_code = self.highlight() 
     super(Snippet, self).save(force_insert, force_update) 

उत्तर

24

super(Snippet, self) का कारण बनता है अजगर स्वयं के वर्ग के MRO (यानी self.__class__.mro()Snippet के बाद सूचीबद्ध अगले वर्ग के लिए में देखने के लिए। यह एक super वस्तु जो उस वर्ग के लिए एक प्रॉक्सी के रूप में कार्य देता है। यही है, वर्ग पर कि विधि बुला तरह super वस्तु में कार्य करता है पर एक विधि बुला।

super(Snippet, self).save(...) कॉल उस वर्ग के save विधि, self पहला तर्क करने के लिए बाध्य है।

तो super(Snippet, self).save(...)Snippet की save विधि को कॉल नहीं करेगा; यह किसी अन्य वर्ग की save विधि को कॉल करेगा। यह सोचने के लिए मोहक है कि यह "अन्य वर्ग" Snippet का "मूल वर्ग" या "सुपरक्लास" है, जो models.Model है, लेकिन यह सच नहीं हो सकता है और super इस तरह से पकड़ना बिल्कुल गलत है। कौन सा वर्ग super(Snippet, self) अंततः प्रतिनिधित्व करता है self और विशेष रूप से इसकी कक्षा के एमआरओ पर निर्भर करता है।

MRO और super (चित्रों के साथ पूर्ण!) का एक बहुत अच्छा विवरण here पाया जा सकता है।

3

मैं फिर क्या unutbu सुपर वर्गों पर समझाया नहीं समझा जाएगा, हालांकि आप निम्न कोड के साथ एक ही प्रभाव प्राप्त:

models.Model.save(self, force_insert, force_update) 

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

मैं यह भी जोड़ सकता हूं कि सुपर निर्देश केवल तभी काम करता है जब आप जिस कक्षा से उत्तीर्ण होते हैं वह ऑब्जेक्ट से विस्तारित होता है, अन्यथा आपको अपवाद मिलता है।

+2

यह केवल तभी नहीं है जब स्निपेट के पूर्वजों को बदल दिया गया हो; यदि स्निपेट के बाल वर्ग में एकाधिक विरासत का एक निश्चित रूप है, तो परिणाम सही 'सुपर (स्निपेट, स्वयं)' से अलग हो सकता है। –