2

je reçois l'erreur: TypeError: __init __() prend exactement 2 arguments (3 donnés)héritage multiple et super appeler()

Lorsque vous essayez d'instancier un objet de la classe Top:

super (Middle1, auto) .__ init __ (nom, "milieu")

class Base(object): 
    def __init__(self, name, type): 
     pass 

class Middle1(Base): 
    def __init__(self, name): 
     super(Middle1, self).__init__(name, "middle1") 

class Middle2(Base): 
    def __init__(self, name): 
     super(Middle2, self).__init__(name, "middle2") 

class Middle3(Base): 
    def __init__(self, name): 
     super(Middle3, self).__init__(name, "middle3") 

class Top(Middle1, Middle2, Middle3): 
    def __init__(self): 
     super(Top, self).__init__("top") 

# Here is where it produces the error 
if __name__ == '__main__': 
    Top() 

Qu'est-ce que je ne comprends sur ce multiple problème de l'héritage?

Note: ceci est python 2.7

EDIT

Ok alors j'ai essayé quelque chose que je pense que des œuvres pour mon cas. C'est le résultat final équivélent, je pense que c'est fondamentalement en forçant la profondeur d'abord en n'appelant pas super et appelant chaque individu __init__ à la place.

class Base(object): 
    def __init__(self, name, type): 
     pass 

class Middle1(Base): 
    def __init__(self, name, type = "middle1"): 
     super(Middle1, self).__init__(name, type) 

class Middle2(Base): 
    def __init__(self, name, type = "middle2"): 
     super(Middle2, self).__init__(name, type) 

class Middle3(Base): 
    def __init__(self, name, type = "middle3"): 
     super(Middle3, self).__init__(name, type) 

class Top(Middle1, Middle2, Middle3): 
    def __init__(self): 
     Middle1.__init__(self, "top") 
     Middle2.__init__(self, "top") 
     Middle3.__init__(self, "top") 

# No errors anymore 
if __name__ == '__main__': 
    Top() 
+0

Ce n'est pas techniquement l'héritage multiple.L'héritage multiple est quand une classe hérite directement de plusieurs classes parentes (et n'est généralement pas supportée dans la plupart des langages de programmation). – apokryfos

+2

Avez-vous vérifié que le fichier de code que vous exécutez est celui que vous montrez ici? Parce que ce code ne produit pas cette erreur ... – dhke

+0

Vous aviez raison. J'ai édité le code pour montrer ma situation actuelle, maintenant il produit cette erreur. – Esser420

Répondre

3

D'abord, vous devez regarder la résolution méthode ordre de Top:

>>> for c in Top.__mro__: print c 
... 
<class '__main__.Top'> 
<class '__main__.Middle1'> 
<class '__main__.Middle2'> 
<class '__main__.Middle3'> 
<class '__main__.Base'> 
<type 'object'> 

Cela vous permet de voir quelle classe chaque appel à représente.

Votre erreur est de penser que l'appel à super(Middle1, self) fait référence à la (seulement) classe de base Base de Middle1. Il ne fait pas: il se réfère à la classe suivante Middle1 dans la MRO de self.__class__. Puisque self.__class__ est Top, la classe suivante est Middle2, dont __init__ prend seulement un argument.

Pour utiliser super correctement à partir d'une méthode, vous devez vous assurer que la méthode prend les mêmes arguments dans toutes les classes , parce que vous ne pouvez pas prédire quelle méthode de classe sera appelée en regardant le code lui-même; cela dépend entièrement du type de l'objet qui initie la chaîne d'appels, qui pourrait être une classe dont vous n'êtes même pas encore conscient.

Il y a deux postes, je vous suggère de lire:

Ensemble, ils vous donnent une bonne compréhension de quand super peut être utilisé correctement et comment éviter le problème que vous voyez ici.

(Dans la divulgation complète, je n'ai pas lu soit après récemment, je vais donc ne pas essayer de résumer les conseils présentés dans chacun.)

+0

Oui c'est surtout ça, je m'attendais à aller en profondeur d'abord puis de gauche à droite. – Esser420

0

Comment instanciez-vous exactement les objets Top?

Étant donné votre code ci-dessus, ce qui suit fonctionne très bien:

topObj = Top() 
    middleObj = Middle("middle") 
    baseObj = Base("base", "type") 
+0

Je vois que vous avez modifié votre exemple de code. En effet, avec l'héritage multiple, la résolution du constructeur devient confuse. – krono