web-dev-qa-db-fra.com

Appelez la méthode d'une classe parent à partir d'une classe enfant en Python?

Lors de la création d'une hiérarchie d'objet simple en Python, j'aimerais pouvoir appeler les méthodes de la classe parente à partir d'une classe dérivée. En Perl et Java, il existe un mot clé pour cela ( super ). En Perl, je pourrais faire ceci:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

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

En python, il apparaît que je dois nommer explicitement la classe parente à partir de l'enfant. Dans l'exemple ci-dessus, je devrais faire quelque chose comme Foo::frotz().

Cela ne semble pas correct, car ce comportement rend difficile la création de hiérarchies profondes. Si les enfants ont besoin de savoir quelle classe a défini une méthode héritée, toutes sortes d'informations douloureuses sont créées.

Est-ce une limitation réelle en python, une lacune dans ma compréhension ou les deux?

530
jjohn

Oui, mais seulement avec classes de style nouvea . Utilisez la fonction super() :

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

Pour Python 3.x, vous pouvez utiliser:

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

Python a aussi super aussi:

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

Renvoie un objet proxy qui délègue des appels de méthode à une classe parent ou parent du type. Ceci est utile pour accéder aux méthodes héritées qui ont été remplacées dans une classe. L'ordre de recherche est identique à celui utilisé par getattr (), sauf que le type lui-même est ignoré.

Exemple:

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

tout ira bien, que la classe parente immédiate définie frotz elle-même ou qu’elle en ait hérité. super n'est nécessaire que pour le support correct de l'héritage multiple (et cela ne fonctionne que si toutes les classes l'utilisent correctement). En général, AnyClass.whatever va rechercher whatever dans les ancêtres de AnyClass si AnyClass ne le définit pas/ne le définit pas, ce qui est vrai pour "la méthode du parent appelant une classe enfant "comme pour tout autre événement!

79
Alex Martelli

Python a une syntaxe différente et plus simple pour appeler une méthode parent.

Si Foo la classe hérite de Bar, alors de Bar.__init__ peut être appelé à partir de Foo via super().__init__():

class Foo(Bar):

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

Beaucoup de réponses ont expliqué comment appeler une méthode du parent qui a été remplacée par l'enfant.

Pourtant

"comment appelez-vous la méthode d'une classe parent à partir de la classe enfant?"

pourrait aussi signifier:

"comment appelez-vous les méthodes héritées?"

Vous pouvez appeler des méthodes héritées d'une classe parente comme s'il s'agissait de méthodes de la classe enfant, à condition qu'elles n'aient pas été écrasées.

par exemple. dans 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"

oui, cela peut paraître assez évident, mais j’ai l’impression que, sans le signaler, il est possible que des personnes laissent ce fil avec l’impression que vous devez sauter à travers des cercles ridicules pour accéder aux méthodes héritées en python. D'autant plus que cette question accorde beaucoup d'importance aux recherches sur "comment accéder à la méthode d'une classe parente en Python", et que l'OP est écrit du point de vue de quelqu'un de novice en python.

J'ai trouvé: https://docs.python.org/3/tutorial/classes.html#inheritance utile pour comprendre comment vous accédez aux méthodes héritées.

37
Ben

Voici un exemple d'utilisation de 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
26
yesnik

Il y a aussi un super () dans Python. C'est un peu bizarre, à cause des classes de style ancien et nouveau de Python, mais il est assez couramment utilisé, par exemple. dans les constructeurs:

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

Je recommanderais d'utiliser CLASS.__bases__ quelque chose comme ceci

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()
9
Joran Beasley

Si vous ne connaissez pas le nombre d'arguments que vous pourriez avoir et que vous souhaitez également les transmettre à l'enfant:

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

(De: Python - Le moyen le plus propre de remplacer __init__ où un kwarg optionnel doit être utilisé après l'appel de super ()? )

6
Robin Winslow

Il y a un super () dans python également.

Exemple pour appeler une méthode de super classe à partir d'une méthode de sous classe

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

Cet exemple est similaire à celui expliqué ci-dessus. Il existe toutefois une différence: aucun argument n'a été transmis à super. Ce code ci-dessus est exécutable dans la version python 3.4.

4
kkk

dans cet exemple, cafec_param est une classe de base (classe parent) et abc est une classe enfant. abc appelle la méthode AWC dans la classe de 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())

sortie

56

56

56

1
Khan

Dans Python 2, je n'ai pas eu beaucoup de chance avec super (). J'ai utilisé la réponse de jimifiki sur ce SO thread comment faire référence à une méthode parente en python? . Ensuite, j’y ai ajouté ma petite touche personnelle, ce qui, à mon avis, constitue une amélioration de la convivialité (surtout si vous avez des noms de classe longs).

Définissez la classe de base dans un module:

 # myA.py

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

Importez ensuite la classe dans un autre module as parent:

# myB.py

from myA import A as parent

class B( parent ):
    def foo( self ):
        parent.foo( self )   # calls 'A.foo()'
1
BuvinJ
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()
0
maryam mehboob