web-dev-qa-db-fra.com

Comment invoquer le super constructeur en Python?

class A:
    def __init__(self):
        print("world")

class B(A):
    def __init__(self):
       print("hello")

B()  # output: hello

Dans toutes les autres langues avec lesquelles j'ai travaillé, le super constructeur est invoqué implicitement. Comment l'invoque-t-on en Python? Je m'attendrais à super(self) mais cela ne fonctionne pas.

317
Mike

super() renvoie un objet de type parent dans les classes de style nouvea:

class A(object):
    def __init__(self):
        print "world"

class B(A):
    def __init__(self):
        print "hello"
        super(B, self).__init__()

B()
310

En ligne avec les autres réponses, il existe de nombreuses manières d'appeler des méthodes de super classe (y compris le constructeur), cependant, dans Python-3.x, le processus a été simplifié:

Python-2.x

class A(object):
 def __init__(self):
   print "world"

class B(A):
 def __init__(self):
   print "hello"
   super(B, self).__init__()

Python-3.x

class A(object):
 def __init__(self):
   print("world")

class B(A):
 def __init__(self):
   print("hello")
   super().__init__()

super() est maintenant équivalent à super(<containing classname>, self) selon la documentation .

209
Aidan Gomez

Avec Python 2.x classes anciennes, ce serait:

class A: 
 def __init__(self): 
   print "world" 

class B(A): 
 def __init__(self): 
   print "hello" 
   A.__init__(self)
52
Gabe

Une solution consiste à appeler le constructeur de A et à passer self comme argument, comme suit:

class B(A):
    def __init__(self):
        A.__init__(self)
        print "hello"

L'avantage de ce style est qu'il est très clair. Il appelle un initialiseur. L'inconvénient est qu'il ne gère pas très bien l'héritage en forme de losange, car vous pourriez éventuellement appeler l'initialiseur de la classe de base partagée à deux reprises.

Une autre méthode consiste à utiliser super (), comme d'autres l'ont montré. Pour un héritage unique, cela revient fondamentalement à vous permettre d'appeler l'initialiseur du parent.

Cependant, super () est un peu plus compliqué et peut parfois être contre-intuitif dans de multiples situations d'héritage. Super () peut être utilisé pour gérer l’héritage en forme de losange. Si vous voulez savoir ce que fait super (), la meilleure explication que j'ai trouvée sur son fonctionnement est ici (bien que je n'approuve pas nécessairement les opinions de cet article) .

32
Daniel Stutzbach

Réponse courte

super(DerivedClass, self).__init__()

Réponse longue

Que fait super()?

Il prend le nom de classe spécifié, trouve ses classes de base (Python autorise l'héritage multiple) et recherche la méthode (__init__ dans ce cas) dans chacune d'elles de gauche à droite. Dès qu'il trouvera une méthode disponible, il l'appellera et mettra fin à la recherche.

Comment appeler init de toutes les classes de base?

Ce qui précède fonctionne si vous n’avez qu’une classe de base. Mais Python autorise un héritage multiple et vous pouvez vous assurer que toutes les classes de base sont initialisées correctement. Pour ce faire, vous devez avoir chaque init de l'appel de classe de base:

class Base1:
  def __init__():
    super(Base1, self).__init__()

class Base2:
  def __init__():
    super(Base2, self).__init__()

class Derived(Base1, Base2):
  def __init__():
    super(Derived, self).__init__()

Et si j'oublie d'appeler init pour super?

Le constructeur (__new__) est appelé dans une chaîne (comme en C++ et Java). Une fois l'instance créée, seul son initialiseur (__init__) est appelé, sans aucune chaîne implicite vers sa superclasse.

2
Shital Shah

J'utilise la formule suivante qui étend les réponses précédentes:

class A(object):
 def __init__(self):
   print "world"

class B(A):
 def __init__(self):
   print "hello"
   super(self.__class__, self).__init__()

B()

De cette façon, vous n'avez pas à répéter le nom de la classe dans l'appel à super. Cela peut s'avérer utile si vous codez un grand nombre de classes et souhaitez rendre votre code dans les méthodes d'initialisation indépendant du nom de la classe.

1
lackadaisical

Juste pour ajouter un exemple avec des paramètres:

class B(A):
    def __init__(self, x, y, z):
        A.__init__(self, x, y)

Étant donné une classe dérivée B nécessitant la définition des variables x, y, z et une superclasse A nécessitant la définition de x, y, vous pouvez appeler la méthode statique init de la superclasse A avec une référence à l'instance de sous-classe actuelle (self), puis à la liste des arguments attendus.

0
gal007