चाइल्ड क्लास से पैरेंट क्लास का तरीका बताएं?


606

पायथन में एक साधारण वस्तु पदानुक्रम बनाते समय, मैं एक व्युत्पन्न वर्ग से मूल वर्ग के तरीकों को लागू करने में सक्षम होना चाहता हूं। पर्ल और जावा में, इसके लिए एक कीवर्ड है ( super)। पर्ल में, मैं यह कर सकता हूं:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

sub frotz {
   my $str = SUPER::frotz();
   return uc($str);
}

पायथन में, ऐसा प्रतीत होता है कि मुझे बच्चे से स्पष्ट रूप से मूल वर्ग का नाम लेना है। ऊपर के उदाहरण में, मुझे कुछ करना होगा Foo::frotz()

यह सही नहीं लगता क्योंकि यह व्यवहार गहरी पदानुक्रम बनाने के लिए कठिन बनाता है। यदि बच्चों को यह जानने की जरूरत है कि किस वर्ग ने विरासत में मिली पद्धति को परिभाषित किया है, तो सभी प्रकार के सूचना दर्द पैदा हो जाते हैं।

क्या यह अजगर में एक वास्तविक सीमा है, मेरी समझ में अंतर है या दोनों है?


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

7
जबकि एक कक्षा का नाम रखने का एक विकल्प एक बुरा विचार नहीं है, ऐसा करने के लिए मजबूर होना निश्चित रूप से है।
जॉन्डोडो

Python 2 और Python 3 https://www.python.org/dev/peps/pep-3135/ के बीच सुपर हैंडलिंग में होने वाले बदलावों से अवगत रहें । वर्ग का नामकरण अब आवश्यक नहीं है (हालांकि अभी भी कम से कम कभी-कभी एक देव विचार हो सकता है)।
jwpfox 21

जवाबों:


735

हां, लेकिन केवल नई शैली की कक्षाओं के साथsuper()फ़ंक्शन का उपयोग करें :

class Foo(Bar):
    def baz(self, arg):
        return super().baz(arg)

अजगर <3 के लिए, उपयोग करें:

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)

53
क्या आप "Bar.baz (self, arg)" भी नहीं कर सकते हैं? यदि हां, तो कौन सा बेहतर होगा?

15
हां, आप कर सकते हैं, लेकिन ओपी पूछ रहा था कि कॉल साइट (बार में इस मामले में) पर सुपरक्लास का नाम लिए बिना इसे स्पष्ट रूप से कैसे किया जाए।
एडम रोसेनफील्ड

7
सुपर () कई विरासत के साथ अजीब है। यह "अगले" वर्ग के लिए कहता है। वह मूल वर्ग हो सकता है, या कुछ पूरी तरह से असंबंधित वर्ग हो सकता है जो पदानुक्रम में कहीं और दिखाई देता है।
स्टीव जेसोप

6
जब मैं ऐसा करता हूं तो मैं पायथन 2.x का उपयोग करता हूं, और मुझे "त्रुटि: टाइप होना चाहिए, क्लासबॉज नहीं"
क्रिस एफ

28
super(Foo, self)पायथन 2.x सही के लिए वाक्यविन्यास है? पायथन 3.x में, super()सही पसंद किया जाता है?
ट्रेवर बॉयड स्मिथ

143

अजगर भी सुपर के रूप में है:

super(type[, object-or-type])

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

उदाहरण:

class A(object):     # deriving from 'object' declares A as a 'new-style-class'
    def foo(self):
        print "foo"

class B(A):
    def foo(self):
        super(B, self).foo()   # calls 'A.foo()'

myB = B()
myB.foo()

7
एडम की तुलना में बेहतर उदाहरण है क्योंकि आपने ऑब्जेक्ट बेस क्लास के साथ एक नई शैली वर्ग का उपयोग करके प्रदर्शन किया है। बस नई शैली की कक्षाओं के लिए लिंक गायब है।
शमूएल

81
ImmediateParentClass.frotz(self)

बस ठीक होगा, चाहे तत्काल अभिभावक वर्ग ने frotzखुद को परिभाषित किया हो या उसे विरासत में मिला हो। superकेवल एकाधिक वंशानुक्रम के उचित समर्थन के लिए आवश्यक है (और तब यह केवल तभी काम करता है जब प्रत्येक वर्ग इसका सही उपयोग करता है)। सामान्य तौर पर, यदि यह परिभाषित नहीं करता है, तो इसे AnyClass.whateverदेखने whateverमें कोई दिक्कत नहीं होगी, या यह किसी अन्य घटना के लिए "माता-पिता की विधि को कॉल करने वाले बच्चे" के लिए सही है!AnyClassAnyClass


यह बताता है कि इस कथन को निष्पादित करने के लिए ImmediateParentClass भी गुंजाइश में मौजूद है। बस मॉड्यूल से आयातित वस्तु होने से मदद नहीं मिलेगी।
तुषार वज़ीरानी

क्या होगा अगर इसकी एक वर्ग विधि?
शिप्लू मोकादिम

@TusharVazirani अगर मूल वर्ग तत्काल है parent, तो यह पूरी कक्षा के दायरे में है, है ना?
यारोस्लाव निकितेंको

1
@YaroslavNikitenko मैं एक उदाहरण आयात करने के बारे में बात कर रहा हूं, न कि वर्ग।
तुषार वाजिरानी

1
@TusharVazirani अब मैं समझता हूं, धन्यवाद। मैं वर्तमान कक्षा की विधि से कॉल करने के बारे में सोच रहा था (जैसा कि ओपी ने कहा था)।
यारोस्लाव निकितेंको

74

मूल विधि को कॉल करने के लिए पायथन 3 में एक अलग और सरल वाक्यविन्यास है।

यदि Fooवर्ग इनहेरिट करता है Bar, तो इसके माध्यम Bar.__init__से इनवाइट किया जा सकता है :Foosuper().__init__()

class Foo(Bar):

    def __init__(self, *args, **kwargs):
        # invoke Bar.__init__
        super().__init__(*args, **kwargs)

5
पायथन 3 सुनने के लिए अच्छा एक बेहतर उपाय है। प्रश्न अजगर 2.X से आता है। फिर भी सुझाव के लिए धन्यवाद।
जॉन्ज

45

कई जवाबों ने समझाया है कि माता-पिता से एक विधि कैसे कॉल करें जो बच्चे में ओवरराइड हो गई है।

तथापि

"आप चाइल्ड क्लास से पेरेंट्स क्लास के तरीके को कैसे कहते हैं?"

बस मतलब भी हो सकता है:

"आप विरासत में मिली विधियों को कैसे कहते हैं?"

आप मूल वर्ग से विरासत में मिली विधियों को कॉल कर सकते हैं जैसे कि वे बच्चे वर्ग के तरीके थे, जब तक कि उन्हें अधिलेखित नहीं किया गया हो।

अजगर 3 में जैसे:

class A():
  def bar(self, string):
    print("Hi, I'm bar, inherited from A"+string)

class B(A):
  def baz(self):
    self.bar(" - called by baz in B")

B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B"

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

मैंने पाया: https://docs.python.org/3/tutorial/classes.html#inherit यह समझने में उपयोगी होने के लिए कि आप विरासत में मिली विधियों का उपयोग कैसे करते हैं।


@gizzmole किस स्थिति में काम नहीं करता है? मैं किसी भी चेतावनी या चेतावनी को जोड़ने के लिए खुश हूं जो प्रासंगिक है, लेकिन मैं यह पता नहीं लगा सका कि आपने जो लिंक पोस्ट किया था वह इस उत्तर के लिए प्रासंगिक था।
बेन

@ क्षमा करें, मैंने आपका उत्तर ध्यान से नहीं पढ़ा। यह उत्तर इस सवाल का जवाब नहीं देता है कि कार्यों को कैसे अधिभारित करना है, लेकिन एक अलग प्रश्न का उत्तर देता है। मैंने अपनी प्रारंभिक टिप्पणी हटा दी।
जिज्मोले

@ जीज़मोल आह, कोई चिंता नहीं। मुझे एहसास है कि यह उत्तर ओवरलोडिंग कार्यों पर लागू नहीं होता है, हालांकि यह सवाल स्पष्ट रूप से ओवरलोडिंग का उल्लेख नहीं करता है (हालांकि दिए गए पर्ल उदाहरण में ओवरलोडिंग का मामला दिखाई देता है)। अन्य उत्तर के अधिकांश भाग ओवरलोडिंग को कवर करते हैं - यह यहां उन लोगों के लिए है जिन्हें इसकी आवश्यकता नहीं है।
बेन

@ अगर मैं B ()। Baz () को C से परिभाषित वर्जन का उपयोग करके 'C' नामक किसी अन्य वर्ग से कॉल करना चाहता हूं तो क्या होगा? मैंने कक्षा C में B ()। Baz () करने की कोशिश की, जहाँ self.string एक और वैल है। यह मुझे कोई नहीं है, जब मैं निष्पादित दिया
जॉय

@joey मुझे यकीन नहीं है कि आप क्या करने की कोशिश कर रहे हैं, या अगर यह इस सवाल के दायरे में है। स्ट्रिंग एक स्थानीय चर है - सेटिंग self.stringकुछ भी नहीं करेगा। कक्षा C में आप फिर भी कॉल कर सकते हैंB().bar(string)
बेन

26

यहाँ सुपर का उपयोग करने का एक उदाहरण है () :

#New-style classes inherit from object, or from another new-style class
class Dog(object):

    name = ''
    moves = []

    def __init__(self, name):
        self.name = name

    def moves_setup(self):
        self.moves.append('walk')
        self.moves.append('run')

    def get_moves(self):
        return self.moves

class Superdog(Dog):

    #Let's try to append new fly ability to our Superdog
    def moves_setup(self):
        #Set default moves by calling method of parent class
        super(Superdog, self).moves_setup()
        self.moves.append('fly')

dog = Superdog('Freddy')
print dog.name # Freddy
dog.moves_setup()
print dog.get_moves() # ['walk', 'run', 'fly']. 
#As you can see our Superdog has all moves defined in the base Dog class

क्या यह एक बुरा उदाहरण नहीं है? मेरा मानना ​​है कि सुपर का उपयोग करना वास्तव में सुरक्षित नहीं है जब तक कि आपकी पूरी पदानुक्रम "नई शैली" कक्षाएं और ठीक से सुपर ()! Init ()
जयकुल

13

पायथन में भी एक सुपर () है। पायथन की पुरानी और नई शैली की कक्षाओं के कारण यह थोड़ा विस्की है, लेकिन निर्माणकर्ताओं में उदाहरण के तौर पर इसका काफी उपयोग किया जाता है:

class Foo(Bar):
    def __init__(self):
        super(Foo, self).__init__()
        self.baz = 5

9

मैं CLASS.__bases__ इस तरह से कुछ का उपयोग करने की सलाह दूंगा

class A:
   def __init__(self):
        print "I am Class %s"%self.__class__.__name__
        for parentClass in self.__class__.__bases__:
              print "   I am inherited from:",parentClass.__name__
              #parentClass.foo(self) <- call parents function with self as first param
class B(A):pass
class C(B):pass
a,b,c = A(),B(),C()

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

7

यदि आप नहीं जानते कि आपको कितने तर्क मिल सकते हैं, और उन सभी को बच्चे तक भी पहुंचाना चाहते हैं:

class Foo(bar)
    def baz(self, arg, *args, **kwargs):
        # ... Do your thing
        return super(Foo, self).baz(arg, *args, **kwargs)

(जब से: पायथन - __init__ को ओवरराइड करने का सबसे अच्छा तरीका है जहाँ सुपर () कॉल के बाद एक वैकल्पिक kwarg का उपयोग किया जाना चाहिए? )


4

अजगर में भी एक सुपर () है।

सुपर क्लास विधि को उप क्लास विधि से कैसे कहा जाता है, इसके लिए उदाहरण

class Dog(object):
    name = ''
    moves = []

    def __init__(self, name):
        self.name = name

    def moves_setup(self,x):
        self.moves.append('walk')
        self.moves.append('run')
        self.moves.append(x)
    def get_moves(self):
        return self.moves

class Superdog(Dog):

    #Let's try to append new fly ability to our Superdog
    def moves_setup(self):
        #Set default moves by calling method of parent class
        super().moves_setup("hello world")
        self.moves.append('fly')
dog = Superdog('Freddy')
print (dog.name)
dog.moves_setup()
print (dog.get_moves()) 

यह उदाहरण ऊपर बताए गए के समान है। जब भी कोई अंतर होता है कि सुपर के पास इसके लिए कोई तर्क नहीं होता है। यह ऊपर कोड अजगर 3.4 संस्करण में निष्पादन योग्य है।


2

इस उदाहरण cafec_paramमें एक बेस क्लास (पैरेंट क्लास) है और abcएक चाइल्ड क्लास है। बेस क्लास में विधि को abcबुलाता है AWC

class cafec_param:

    def __init__(self,precip,pe,awc,nmonths):

        self.precip = precip
        self.pe = pe
        self.awc = awc
        self.nmonths = nmonths

    def AWC(self):

        if self.awc<254:
            Ss = self.awc
            Su = 0
            self.Ss=Ss
        else:
            Ss = 254; Su = self.awc-254
            self.Ss=Ss + Su   
        AWC = Ss + Su
        return self.Ss


    def test(self):
        return self.Ss
        #return self.Ss*4

class abc(cafec_param):
    def rr(self):
        return self.AWC()


ee=cafec_param('re',34,56,2)
dd=abc('re',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())

उत्पादन

56

56

56

1

पायथन 2 में, मेरे पास सुपर () के साथ बहुत कुछ नहीं था। मैंने इस SO थ्रेड पर jimifiki से उत्तर का उपयोग किया था कि अजगर में मूल विधि का संदर्भ कैसे दें?। फिर, मैंने इसमें अपना थोड़ा सा जुड़ाव जोड़ा, जो मुझे लगता है कि प्रयोज्यता में सुधार है (विशेषकर यदि आपके पास लंबे वर्ग के नाम हैं)।

आधार वर्ग को एक मॉड्यूल में परिभाषित करें:

 # myA.py

class A():     
    def foo( self ):
        print "foo"

फिर कक्षा को अन्य मॉड्यूल में आयात करें as parent:

# myB.py

from myA import A as parent

class B( parent ):
    def foo( self ):
        parent.foo( self )   # calls 'A.foo()'

2
तब आपको सुपर () के class A(object): बजाय उपयोग करना class A():होगा
१ev को

मुझे यकीन नहीं है कि मैं पीछा कर रहा हूं। क्या आप कक्षा की परिभाषा में हैं? जाहिर है, आपको यह संकेत देना होगा कि किसी माता-पिता को संदर्भित करने के लिए एक वर्ग के पास माता-पिता किसी तरह हैं! चूंकि, मैंने इसे 9 महीने पहले पोस्ट किया था, मैं विवरणों के बारे में थोड़ा अस्पष्ट हूं, लेकिन मुझे लगता है कि मेरा मतलब अरुण घोष, लॉरेंस, केकेके आदि से है, जो कि Py 2.x में लागू नहीं हैं। इसके बजाय, यहां एक विधि है जो काम करती है और माता-पिता को संदर्भित करने का एक आसान तरीका है इसलिए यह थोड़ा अधिक स्पष्ट है कि आप क्या कर रहे हैं। (जैसे सुपर का उपयोग करना)
बुविएनजे

-1
class department:
    campus_name="attock"
    def printer(self):
        print(self.campus_name)

class CS_dept(department):
    def overr_CS(self):
        department.printer(self)
        print("i am child class1")

c=CS_dept()
c.overr_CS()

-4
class a(object):
    def my_hello(self):
        print "hello ravi"

class b(a):
    def my_hello(self):
    super(b,self).my_hello()
    print "hi"

obj = b()
obj.my_hello()

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

-24

यह एक अधिक सार विधि है:

super(self.__class__,self).baz(arg)

15
self .__ class__ सुपर के साथ सही काम नहीं करता है क्योंकि स्वयं हमेशा उदाहरण है और इसका वर्ग हमेशा आवृत्ति का वर्ग है। इसका मतलब है कि यदि आप एक वर्ग में सुपर (स्वयं .__ class__ ..) का उपयोग करते हैं और उस वर्ग को विरासत में मिला है, तो यह अब काम नहीं करेगा।
xitrium

16
बस जोर देने के लिए, इस कोड का उपयोग न करें। यह सुपर के पूरे उद्देश्य () को हरा देता है, जो एमआरओ को सही ढंग से पीछे हटाना है।
Eevee

1
stackoverflow.com/a/19257335/419348 ने कहा कि फोन क्यों नहीं करते super(self.__class__, self).baz(arg)
अचलोइलू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.