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


Lors de la création d'une hiérarchie d'objets simple en Python, j'aimerais pouvoir appeler des méthodes de la classe parent à partir d'une classe dérivée. En Perl et Java, il y a 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, alors toutes sortes d'informations sont créées.

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


419
2018-04-30 01:52


origine


Réponses:


Oui, mais seulement avec cours de style nouveau. Utilisez le super() fonction:

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

504
2018-04-30 01:58



Python a aussi super ainsi que:

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

Renvoie un objet proxy qui délègue des appels de méthode à un parent ou à une classe de type frère.   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 le même que 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()

97
2018-04-30 01:58



ImmediateParentClass.frotz(self)

sera très bien, que la classe parent immédiate définie frotz lui-même ou l’a hérité. super est seulement nécessaire pour un soutien approprié de plusieurs héritage (et alors cela ne fonctionne que si chaque classe l'utilise correctement). En général, AnyClass.whatever va chercher whatever dans AnyClassles ancêtres si AnyClass ne le définit pas / ne le remplace pas, et ceci est vrai pour la "méthode du parent appelant la classe du parent" comme pour toute autre occurrence!


70
2018-04-30 02:02



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

class Foo(Bar):
    def __init__(self):
        super().__init__()

30
2017-07-26 10:12



Voici un exemple d'utilisation 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
2018-04-17 10:44



De nombreuses réponses expliquent comment appeler une méthode du parent qui a été remplacée par l'enfant.

toutefois

"Comment appelez-vous la méthode d'une classe parente 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 si elles étaient des méthodes de la classe enfant, à condition qu'elles n'aient pas été remplacées.

par exemple. 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 le signaler, 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 a un taux élevé dans les recherches pour "comment accéder à la méthode d'une classe parente en Python", et l'OP est écrit du point de vue de quelqu'un de nouveau à python.

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


20
2017-07-11 14:32



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

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

13
2018-04-30 01:58



Je recommanderais 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
2017-12-31 17:39



Si vous ne connaissez pas le nombre d'arguments que vous pourriez avoir, et que vous voulez 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 simple de remplacer __init__ où un kwarg optionnel doit être utilisé après l'appel à super ()?)


5
2017-12-09 16:13



Il y a aussi un super () en python.

Exemple de méthode d'appel d'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. Cependant, il y a une différence que super n'a pas d'arguments transmis. Ce code ci-dessus est exécutable dans la version de python 3.4.


4
2017-12-10 13:21