Appeler la méthode d'une classe parent de la classe enfant en Python?

lors de la création d'une simple hiérarchie d'objets en Python, j'aimerais pouvoir invoquer les méthodes de la classe mère à partir d'une classe dérivée. En Perl et Java, il y a un mot clé pour ceci ( 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 semble que je doive nommer la classe parent explicitement à partir de l'enfant. Dans l'exemple ci-dessus, je devrais faire quelque chose comme Foo::frotz() .

This ne semble pas juste, car ce comportement rend difficile les grandes hiérarchies. Si les enfants ont besoin de savoir quelle classe définit une méthode héritée, puis toutes sortes d'informations douleur est créé.

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

430
demandé sur Filipp W. 2009-04-30 05:52:31

13 réponses

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

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)
522
répondu Adam Rosenfield 2009-04-30 01:58:28

Python a aussi super ainsi:

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

renvoie un objet de procuration qui délègue les appels de méthode à une classe de type de parent ou de frère ou sœur. Ceci est utile pour accéder aux méthodes héritées qui ont été dépassées dans une classe. L'ordre de recherche est le même que celui utilisé par getattr (), sauf que le type lui-même est ignorée.

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()
99
répondu Jay 2016-09-16 11:18:01
ImmediateParentClass.frotz(self)

sera très bien, que la classe de parent immédiate défini frotz elle-même ou héritée. super est seulement nécessaire pour le soutien approprié de héritage multiple (et alors il ne fonctionne que si chaque classe l'utilise correctement). En général, AnyClass.whatever va chercher whatever dans AnyClass 's ancêtres si AnyClass ne définit pas / override it, et cela vaut pour "child class calling parent's method" comme pour toute autre événement!

71
répondu Alex Martelli 2014-10-17 06:53:06

Python 3 a une syntaxe différente et plus simple pour appeler la méthode parent. Si la classe Foo hérite de Bar , alors la classe Bar.__init__ peut être invoquée de Foo en utilisant super().__init__() :

class Foo(Bar):
    def __init__(self):
        super().__init__()
33
répondu Arun Ghosh 2016-07-26 10:12:08

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
25
répondu yesnik 2014-05-26 03:05:18

beaucoup de réponses ont expliqué comment appeler une méthode du parent qui a été dépassé dans l'enfant.

cependant

" comment appelez-vous la méthode de la classe des parents de la classe des enfants?"

pourrait aussi signifier:

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

vous pouvez appeler des méthodes héritées d'une classe parent juste comme s'ils étaient des méthodes de la classe enfant, tant qu'ils n'ont pas été écrasés.

p.ex. en 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 être assez évident, mais je pense que sans souligner cela, les gens peuvent laisser ce fil avec l'impression que vous devez sauter à travers des cerceaux ridicules juste pour accéder aux méthodes héritées en python. D'autant plus que cette question est très importante dans les recherches de "comment accéder à la méthode d'une classe mère en Python", et OP est écrit du point de vue de quelqu'un de nouveau en python.

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

21
répondu Ben 2017-07-11 14:32:30

il y a un super() en Python aussi. C'est un peu compliqué, à cause des anciennes et des nouvelles classes 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
répondu lawrence 2009-04-30 03:52:59

je recommande d'utiliser CLASS.__bases__ quelque chose comme ça

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
répondu Joran Beasley 2011-12-31 17:39:11

si vous ne savez pas combien d'arguments vous pourriez avoir, et que vous voulez les transmettre à l'enfant aussi bien:

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

(à Partir de: Python - façon la plus Propre à remplacer __init__, où une option de kwarg doit être utilisé après l'appel super ()? )

5
répondu Robin Winslow 2017-05-23 12:02:48

il y a aussi un super() en python.

exemple pour la façon dont une méthode de super classe est appelée à 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 cependant une différence que super n'ont pas d'arguments transmis.Ce code ci-dessus est exécutable en version Python 3.4.

4
répondu kkk 2014-12-10 13:21:18

en Python 2, Je n'ai pas eu beaucoup de chance avec super(). J'ai utilisé la réponse de jimifiki sur ce fil SO comment se référer à une méthode parent en python? . Puis, j'y ai ajouté ma propre petite touche, ce qui, je pense, est une amélioration de la convivialité (surtout si vous avez de longs noms de classe).

définit la classe de base dans un module:

 # myA.py

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

puis importer 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
répondu BuvinJ 2017-05-23 10:31:37
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()
-3
répondu RAVIKUMAR RACHA 2018-08-31 14:29:02

c'est une méthode plus abstraite:

super(self.__class__,self).baz(arg)
-21
répondu user806071 2011-06-20 07:35:59