2015-05-04 8 views
15

रेमंड हेटिंगर की बात "Super considered super speak" में पीईसीओएन 2015 में वह कई विरासत संदर्भ में पाइथन में super का उपयोग करने के फायदे बताते हैं। self.get_dough() बजाय super().get_dough() का उपयोग कर के अंतर के बारे में दर्शकों asked रेमंड मेंपायथन स्व और सुपर एकाधिक विरासत में सुपर

class DoughFactory(object): 
    def get_dough(self): 
     return 'insecticide treated wheat dough' 


class Pizza(DoughFactory): 
    def order_pizza(self, *toppings): 
     print('Getting dough') 
     dough = super().get_dough() 
     print('Making pie with %s' % dough) 
     for topping in toppings: 
      print('Adding: %s' % topping) 


class OrganicDoughFactory(DoughFactory): 
    def get_dough(self): 
     return 'pure untreated wheat dough' 


class OrganicPizza(Pizza, OrganicDoughFactory): 
    pass 


if __name__ == '__main__': 
    OrganicPizza().order_pizza('Sausage', 'Mushroom') 

किसी: यह उदाहरण है कि रेमंड उनकी बात के दौरान इस्तेमाल में से एक है। मुझे रेमंड के संक्षिप्त उत्तर को बहुत अच्छी तरह से समझ में नहीं आया, लेकिन मैंने अंतर देखने के लिए इस उदाहरण के दो कार्यान्वयन को कोडित किया। उत्पादन दोनों ही मामलों के लिए ही कर रहे हैं: यदि आप super().get_dough() इस का उपयोग

Making pie with pure untreated wheat dough

हालांकि:

Getting dough 
Making pie with pure untreated wheat dough 
Adding: Sausage 
Adding: Mushroom 

आप self.get_dough() का उपयोग कर OrganicPizza(Pizza, OrganicDoughFactory) से वर्ग आदेश OrganicPizza(OrganicDoughFactory, Pizza) को बदलने, तो आप इस परिणाम मिल जाएगा आउटपुट है:

Making pie with insecticide treated wheat dough

मैं super() व्यवहार को समझता हूं क्योंकि रेमंड ने समझाया था। लेकिन एकाधिक विरासत परिदृश्य में self के अपेक्षित व्यवहार क्या हैं?

+0

क्या - पिज्जा * आटा कारखाने * से प्राप्त होता है? यह कोड अजीब है। – user2357112

+0

'स्वयं' वस्तु के किसी भी अन्य संदर्भ की तरह व्यवहार करता है। यदि आप 'p = OrganicPizza()' करते हैं, तो 'p' की किसी भी विधि में 'self.get_dough()' 'p.get_dough()' के बराबर है, इससे कोई फर्क नहीं पड़ता कि विरासत में' self' का उपयोग कहां है होता है। क्या आप समझते हैं कि 'p.get_dough() 'क्या करेगा? – user2357112

+0

@ user2357112 अजीब क्यों है? रेमंड ने अपनी बातचीत में प्रस्तावित एक साधारण उदाहरण है। –

उत्तर

12

बस स्पष्ट करने के लिए, चार मामलों Pizza.order_pizza में दूसरी पंक्ति और OrganicPizza की परिभाषा बदल रहा है के आधार पर देखते हैं,:

  1. super(), (Pizza, OrganicDoughFactory)(मूल): 'Making pie with pure untreated wheat dough'
  2. self, (Pizza, OrganicDoughFactory): 'Making pie with pure untreated wheat dough'
  3. super(), (OrganicDoughFactory, Pizza): 'Making pie with insecticide treated wheat dough'
  4. self, (OrganicDoughFactory, Pizza): 'Making pie with pure untreated wheat dough'

प्रकरण 3. एक है कि आप को हैरान कर दिया है; अगर हम विरासत के आदेश को स्विच करते हैं लेकिन अभी भी super का उपयोग करते हैं, तो हम स्पष्ट रूप से मूल DoughFactory.get_dough पर कॉल करना समाप्त कर देते हैं।


क्या super वास्तव में करता है पूछना है "जो एमआरओ (विधि संकल्प आदेश) में अगले है?" तो OrganicPizza.mro() जैसा दिखता है?

  • (Pizza, OrganicDoughFactory): [<class '__main__.OrganicPizza'>, <class '__main__.Pizza'>, <class '__main__.OrganicDoughFactory'>, <class '__main__.DoughFactory'>, <class 'object'>]
  • (OrganicDoughFactory, Pizza): [<class '__main__.OrganicPizza'>, <class '__main__.OrganicDoughFactory'>, <class '__main__.Pizza'>, <class '__main__.DoughFactory'>, <class 'object'>]

महत्वपूर्ण यहाँ सवाल है: जो Pizza के बाद आता है? चूंकि हम को Pizza के अंदर से कॉल कर रहे हैं, यही वह जगह है जहां पायथन get_dough * ढूंढने के लिए जाएंगे। 1. और 2 के लिए।यह OrganicDoughFactory है, इसलिए हमें शुद्ध, इलाज न किए गए आटा मिलते हैं, लेकिन 3. और 4. के लिए यह मूल, कीटनाशक-उपचार DoughFactory है।


self क्यों अलग है? self हमेशा उदाहरण है, इसलिए पाइथन एमआरओ की शुरुआत से get_dough की तलाश में जाता है। जैसा कि ऊपर दिखाया गया है, OrganicDoughFactoryDoughFactory की तुलना में पहले सूची में है, यही कारण है कि self संस्करण हमेशा इलाज न किए गए आटा; self.get_dough हमेशा OrganicDoughFactory.get_dough(self) पर हल करता है।


* मुझे लगता है कि यह वास्तव में super पायथन 2.x में इस्तेमाल के दो तर्क रूप है, जो super(Pizza, self).get_dough() होगा में स्पष्ट है; पहला तर्क वर्ग छोड़ने के लिए वर्ग है (यानी उस कक्षा के बाद बाकी एमआरओ में पाइथन दिखता है)।

+0

उत्कृष्ट उत्तर के लिए धन्यवाद .. – javed

2

मैं इस पर कुछ अवलोकन साझा करना चाहता हूं।

कॉलिंग self.get_dough() संभव नहीं हो सकता आप माता-पिता वर्ग के get_dough() विधि अधिभावी कर रहे हैं, यहाँ की तरह:

class AbdullahStore(DoughFactory): 
    def get_dough(self): 
     return 'Abdullah`s special ' + super().get_dough() 

मुझे लगता है कि इस अभ्यास में एक लगातार परिदृश्य है। अगर हम सीधे DoughFactory.get_dough(self) पर कॉल करते हैं तो व्यवहार ठीक हो जाता है। AbdullahStore प्राप्त करने वाली कक्षा को पूर्ण विधि को ओवरराइड करना होगा और AbdullahStore के 'अतिरिक्त मूल्य' का पुन: उपयोग नहीं कर सकता है। दूसरी ओर, अगर हम super.get_dough(self) उपयोग करते हैं, यह एक टेम्पलेट की एक स्वाद: AbdullahStore से प्राप्त किसी भी वर्ग में , कहते हैं कि

class Kebab(AbdullahStore): 
    def order_kebab(self, sauce): 
     dough = self.get_dough() 
     print('Making kebab with %s and %s sauce' % (dough, sauce)) 

हम 'इन्स्तांत' get_dough() अलग ढंग से AbdullahStore में इस्तेमाल किया जा सकता है, एमआरओ में यह अवरोध डालने के इस

class OrganicKebab(Kebab, OrganicDoughFactory):pass 

की तरह यहाँ यह क्या करता है:

Kebab().order_kebab('spicy') 
Making kebab with Abdullah`s special insecticide treated wheat dough and spicy sauce 
OrganicKebab().order_kebab('spicy') 
Making kebab with Abdullah`s special pure untreated wheat dough and spicy sauce 

के बाद सेमें एक एकल माता-पिता DoughFactory है, मुझे DoughFactory से पहले एमआरओ में डालने की गारंटी है और इस प्रकार एमआरओ में सभी पिछली कक्षाओं के लिए इसके तरीकों को ओवरराइड करता है। एमआरओ बनाने के लिए इस्तेमाल किए गए सी 3 रैखिकरण एल्गोरिदम को समझने में मुझे कुछ समय लगा। समस्या यह है कि दो नियमों

children come before parents 
parents order is preserved 

इस संदर्भ https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ से अभी तक स्पष्ट रूप से आदेश को परिभाषित नहीं है। (; वर्ग बी (ए), वर्ग सी (बी), वर्ग ई (ए), वर्ग डी (सी, ई) वर्ग ए) जहां ई एमआरओ में डाला जाएगा वर्ग पदानुक्रम

D->C->B->A 
\ /
    --E-- 

में? क्या यह डीसीबीईए या डीसीईबीए है? शायद इससे पहले कि कोई इस तरह के सवालों का आश्वस्त रूप से जवाब दे सके, यह हर जगह super डालने शुरू करना इतना अच्छा विचार नहीं है। मुझे अभी भी पूरी तरह से यकीन नहीं है, लेकिन मुझे लगता है कि सी 3 रैखिकरण, अस्पष्ट है और इस उदाहरण में डीसीबीईए को ऑर्डर करने का विकल्प चुनता है, हमें अवरोध करने की अनुमति देता है जिस तरह से हमने इसे किया है, अनजाने में।

अब, मुझे लगता है आप

class KebabNPizza(Kebab, OrganicPizza): pass 
KebabNPizza().order_kebab('hot') 

का परिणाम है जो एक बेहतर कबाब है भविष्यवाणी कर सकते हैं:

Making kebab with Abdullah`s special pure untreated wheat dough and hot sauce 

लेकिन यह शायद आप कुछ समय की गणना करने के ले लिया है।

जब मैं पहली बार एक कमजोर पहले super डॉक्स https://docs.python.org/3.5/library/functions.html?highlight=super#super को देखा, सी ++ पृष्ठभूमि से आ रही है, यह की तरह था "वाह, ठीक है यहाँ नियम हैं, लेकिन यह कैसे कभी काम कर सकते हैं और वापस में आप ठूंठ नहीं?"। अब मैं इसके बारे में और अधिक समझता हूं, लेकिन अभी भी super डालने से अनिच्छुक है। मुझे लगता है कि मैंने देखा है कि अधिकांश कोडबेस इसे सिर्फ इसलिए कर रहा है क्योंकि super() बेस क्लास नाम से टाइप करना अधिक सुविधाजनक है। और यह __init__ कार्यों को चेन करने में super() के अत्यधिक उपयोग के बारे में भी बात नहीं कर रहा है। मैं अभ्यास में जो देखता हूं वह यह है कि हर कोई उस हस्ताक्षर के साथ रचनाकार लिखता है जो वर्ग (और सार्वभौमिक नहीं) के लिए सुविधाजनक है और super() का उपयोग करने के लिए उनका बेस क्लास कन्स्ट्रक्टर कहता है।

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