Domanda

Quando creo una semplice gerarchia di oggetti in Python, vorrei poter invocare metodi della classe genitore da una classe derivata. In Perl e Java esiste una parola chiave per questo ( super ). In Perl, potrei farlo:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

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

In Python, sembra che devo nominare esplicitamente la classe genitore dal figlio. Nell'esempio sopra, dovrei fare qualcosa come Foo :: frotz () .

Questo non sembra giusto, poiché questo comportamento rende difficile creare gerarchie profonde. Se i bambini hanno bisogno di sapere quale classe ha definito un metodo ereditato, allora viene creato ogni sorta di dolore informativo.

È una vera limitazione in Python, una lacuna nella mia comprensione o entrambi?

È stato utile?

Soluzione

Sì, ma solo con nuove classi di stile . Utilizza la funzione super () :

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

Per Python 3.x, puoi usare:

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

Altri suggerimenti

Python ha anche super :

super (tipo [, oggetto o tipo])

  

Restituisce un oggetto proxy che delega le chiamate di metodo a una classe di tipo genitore o fratello.   Ciò è utile per accedere a metodi ereditati che sono stati sovrascritti in una classe.   L'ordine di ricerca è uguale a quello utilizzato da getattr () tranne per il fatto che il tipo stesso viene ignorato.

Esempio:

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()
ImmediateParentClass.frotz(self)

andrà bene, indipendentemente dal fatto che la classe genitrice immediata abbia definito frotz o ereditata. super è necessario solo per il corretto supporto dell'ereditarietà multipla (e quindi funziona solo se ogni classe la usa correttamente). In generale, AnyClass.whatever cercherà qualunque cosa negli antenati di AnyClass se AnyClass non funziona definiscilo / sostituiscilo, e questo vale per "quot child class chiamando il metodo parent" come per ogni altra occorrenza!

Python 3 ha una sintassi diversa e più semplice per chiamare il metodo parent.

Se la classe Foo eredita da Bar , da Bar .__ init__ può essere invocato da Foo tramite < code> super () .__ init __ () :

class Foo(Bar):

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

Molte risposte hanno spiegato come chiamare un metodo dal genitore che è stato ignorato nel figlio.

Tuttavia

  

" come si chiama il metodo di una classe genitore dalla classe figlio? "

potrebbe anche significare solo:

  

" come si chiamano i metodi ereditati? "

Puoi chiamare metodi ereditati da una classe genitore proprio come se fossero metodi della classe figlio, purché non siano stati sovrascritti.

es. in Python 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"

sì, questo può essere abbastanza ovvio, ma sento che senza sottolineare questo le persone potrebbero lasciare questo thread con l'impressione che devi saltare attraverso cerchi ridicoli solo per accedere ai metodi ereditati in Python. Soprattutto perché questa domanda è molto indicata nelle ricerche per "come accedere al metodo di una classe genitore in Python" e l'OP è scritto dal punto di vista di qualcuno che è nuovo su Python.

Ho trovato: https://docs.python.org/3/tutorial/classes.html#inheritance per essere utile per capire come accedi ai metodi ereditati.

Ecco un esempio dell'uso di super () :

#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

C'è un super () anche in Python. È un po 'traballante, a causa delle classi di vecchio e nuovo stile di Python, ma è abbastanza comunemente usato ad es. nei costruttori:

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

Consiglierei di usare CLASS .__ bases__ qualcosa del genere

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()

Se non sai quanti argomenti potresti ottenere e vuoi trasmetterli anche al bambino:

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

(Da: Python - Il modo più pulito per sovrascrivere __init__ dove un kwarg opzionale deve essere usato dopo la chiamata super ()? )

Esiste anche un super () in Python.

Esempio di come viene chiamato un metodo di superclasse da un metodo di sottoclasse

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()) 

Questo esempio è simile a quello spiegato sopra.Tuttavia c'è una differenza che super non ha alcun argomento passato ad esso. Questo codice sopra è eseguibile nella versione 3.4 di Python.

In Python 2, non ho avuto molta fortuna con super (). Ho usato la risposta di jimifiki su questo thread SO come fare riferimento a un metodo parent in python ? . Quindi, ho aggiunto la mia piccola svolta ad esso, che penso sia un miglioramento dell'usabilità (specialmente se hai nomi di classe lunghi).

Definisce la classe base in un modulo:

 # myA.py

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

Quindi importare la classe in altri moduli come parent :

# myB.py

from myA import A as parent

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

in questo esempio cafec_param è una classe base (classe genitore) e abc è una classe figlio. abc chiama il metodo AWC nella classe base.

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())

Output

56

56

56

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()
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()

Questo è un metodo più astratto:

super(self.__class__,self).baz(arg)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top