2017-08-26 25 views
5

मैं निम्नलिखित कोडप्रिंट करने की अपेक्षा करता हूं लेकिन यह 012012 प्रिंट करता है। क्यों? मैं उम्मीद करता हूं कि कॉल उसी वैरिएबल तक पहुंचने में शामिल हों क्योंकि उन्हें एक ही कक्षा से विरासत में मिला है लेकिन वे स्पष्ट रूप से भिन्न चर हैं।पायथन कक्षा के तरीके और विरासत

class a(object): 
    var = 0 
    @classmethod 
    def incr(cls): 
     print cls.var 
     cls.var+=1 

class b(a): 
    def func(self): 
     super(b,self).incr() 

class c(a): 
    def func(self): 
     super(c,self).incr() 


t = a() 
t1 = b() 
t2 = c() 
t1.func() 
t1.func() 
t1.func() 
t2.func() 
t2.func() 
t2.func() 
+1

यह अप्रत्याशित व्यवहार को प्रभावित नहीं करता आप देख रहे हैं, लेकिन मैं यह ध्यान रखना चाहता हूं कि आपको अपने उप-वर्गों में यहां 'सुपर' का उपयोग करने की आवश्यकता नहीं है। आप इसके बजाय 'self.incr()' को कॉल कर सकते हैं। जब आप फ़ंक्शन के किसी भिन्न संस्करण को छोड़ना चाहते हैं तो आपको केवल 'सुपर' का उपयोग करने की आवश्यकता होती है (आमतौर पर क्योंकि आपने वर्तमान कक्षा में ओवरराइड किया है)। – Blckknght

+0

आपको पायथन 3.6 पर स्विच करना चाहिए। https://pythonclock.org/ – wwii

उत्तर

5

वे एक ही कक्षा से लिए गए हैं, लेकिन cls सुपर के माध्यम से classmethod के लिए पारित वर्तमान वर्ग जहां विधि से बुलाया गया था है। super विधि के बेस क्लास संस्करण तक पहुंचता है, लेकिन कॉल के लिए cls वह कक्षा है जहां सुपर कॉल किया गया था।

यह कर के बीच सूक्ष्म मतभेद में से एक है:

def func(self): 
    super(c, self).incr() # same as a.__dict__['incr'].__get__(self, type(self))() 

और:

def func(self): 
    a.incr() 

आप दोनों ही मामलों में अपने incr विधि में वर्तमान cls मुद्रण द्वारा इस बात की पुष्टि कर सकते हैं:

आपको कभी यह नहीं मानना ​​चाहिए कि सभी super माता-पिता वर्ग के लिए एक विधि कॉल बाध्य है। यह बहुत कुछ करता है।

ध्यान रखें कि जब पहली संवर्धित असाइनमेंट += किया जाता है, तो var का प्रारंभिक मान बेस क्लास से पढ़ा जाता है (क्योंकि इस बिंदु पर यह सबक्लास के नियम में मौजूद नहीं है)। अद्यतन मूल्य हालांकि उप-वर्ग में लिखा गया है। दूसरे उपclass से super पर कॉलिंग a से प्रारंभिक var मान पढ़ने के समान व्यवहार को दोहराता है।

+0

आप इस तथ्य के बारे में स्पष्ट होना चाहेंगे कि यह 'cls.var + = 1' पंक्ति है जो' cls' अलग होने पर अजीब तरीके से व्यवहार करती है। पहली बार यह चल रहा है, यह * 'var' के विरासत मान को पढ़ता है (जो कि उदाहरण में' 0' है, लेकिन अगर t.incr() 'कहा गया था तो कुछ अन्य मूल्य हो सकता था, लेकिन यह * बेस क्लास की बजाय विशिष्ट 'cls' को लिखता है। बाद की कॉल बेस क्लास को देखे बिना सबक्लास के मूल्य का उपयोग करती हैं। – Blckknght

+0

@Blckknght मैं इसके बारे में एक संक्षिप्त नोट जोड़ दूंगा। –

0

दोनों कक्षा b और कक्षा c कक्षा a कक्षा से अलग है, और var प्रत्येक बार 0 पर सेट है।

एक ही रास्ता के रूप में वर्ग b करता है, वर्ग c तो जैसे वर्ग b से विरासत सकते वर्ग a में var का एक ही मूल्य प्राप्त करने के वर्ग c के लिए:

class a(object): 
    var = 0 
    @classmethod 
    def incr(cls): 
     print cls.var 
     cls.var+=1 

class b(a): 
    def func(self): 
     super(b,self).incr() 

class c(b): 
    def func(self): 
     super(c,self).incr() 


t = a() 
t1 = b() 
t2 = c() 
t1.func() 
t1.func() 
t1.func() 
t2.func() 
t2.func() 
t2.func()` 
+1

यह केवल अपेक्षित परिणाम देता है यदि 't2.func()' पर पहली कॉल सभी 't1.func()' कॉल के बाद आता है। यदि आप उन्हें मिश्रित करते हैं, तो आपको वह नतीजा नहीं मिलेगा जो आप उम्मीद करेंगे। और यह कहना बहुत भ्रामक है कि "var' प्रत्येक बार 0 पर सेट है"। शून्य होने पर केवल एक 'var' है (' a' में से एक)।यह पहली 'incr' कॉल के बाद है कि जिस भी वर्ग को बनाया गया था वह मान '1' के साथ एक नया 'var' विशेषता प्राप्त करता है। – Blckknght

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