2010-11-29 5 views
17

Pendant ce temps, je l'ai utilisé:Python - quelle est la meilleure façon d'appeler la méthode de superclasse?

SuperClass.__init__(self, *args, **kwargs) 

Ma raison est que cela montre explicitement que superclasse est utilisé, en particulier dans le cas de l'héritage multiple.

Cependant, d'autres codes je suis tombé sur l'utilisation

super(MyClass, self).__init__(*args, **kwargs) 

à la place.

Cela pourrait devenir quand il est mal assurés utilisé dans:

class MyClass(SuperClass1, SuperClass2): 
    def __init__(self, *args, **kwargs): 
     super(MyClass, self).__init__(*args, **kwargs) #which SuperClass is being used? 

Je voudrais savoir pourquoi cette forme d'appel est largement adopté? Un avantage du tout?

Répondre

6

Pour les classes de nouveau style héritant de object, super est utilisé.

L'attribut des la résolution de la méthode ordre de recherche des listes de type __mro__ (ordre de résolution de la méthode) utilisée par super.

>>> class X(object): 
    pass 

>>> class Y(object): 
    pass 

>>> class Z(X, Y): 
    pass 

>>> Z.__mro__ 
(<class '__main__.Z'>, <class '__main__.X'>, <class '__main__.Y'>, <type 'object'>) 

Ceci spécifie l'ordre pour Z. Comme il est Z(X, Y), X est d'abord dans la hiérarchie. S'il avait été Z(Y, X), Y aurait précédé plus de X.

Pour les anciennes classes de style, SuperClass.__init__(self, *args, **kwargs) est utilisé.

MISE À JOUR:

Pour votre question à laquelle SuperClass est utilisé.

>>> class First(object): 
    pass 

>>> class Second(object): 
    def __init__(self, *args, **kwargs): 
     print 'Second __init__ called' 

>>> class MInherit(First, Second): 
    def __init__(self): 
     super(MInherit, self).__init__() 

>>> i = MInherit() 
Second __init__ called 

D'abord, First sera vérifié pour voir si elle a une __init__, depuis First vient en premier dans la MRO. Puisque dans ce cas 'First' n'a pas de __init__, alors Second est appelée. S'il y avait eu __init__ dans First, seulement cela aurait été appelé.

21

La raison pour laquelle super est prefereable pour les classes modernes (nouveau style) est qu'il permet coopératif héritage multiple. Voici un exemple.

>>> class Foo(object): 
...  def display(self): 
...   print "In Foo" 
... 
>>> class Foo2(Foo): 
...  def display(self): 
...   print "In Foo2" 
...   super(Foo2, self).display() 
...   print "Back in Foo2" 
... 
>>> class Bar(Foo): 
...  def display(self): 
...   print "In Bar" 
...   super(Bar, self).display() 
...   print "Back in Bar" 
... 
>>> class FooBar(Foo2, Bar): 
...  pass 
... 
>>> FooBar().display() 
In Foo2 
In Bar 
In Foo 
Back in Bar 
Back in Foo2 
>>> class BarFoo(Bar, Foo2): 
...  pass 
... 
>>> BarFoo().display() 
In Bar 
In Foo2 
In Foo 
Back in Foo2 
Back in Bar 

Notez que je ne faisais rien pour changer la méthode display sur les superclasses mais j'ai différentes méthodes display sur les sous-classes en changeant l'ordre dans lequel je me suis arrangé les superclasses. BarFoo et FooBar ont des méthodes différentes. C'est parce qu'ils ont des méthode des ordonnances de résolution

>>> BarFoo.__mro__ 
(<class '__main__.BarFoo'>, <class '__main__.Bar'>, <class '__main__.Foo2'>, <class '__main__.Foo'>, <type 'object'>) 
>>> FooBar.__mro__ 
(<class '__main__.FooBar'>, <class '__main__.Foo2'>, <class '__main__.Bar'>, <class '__main__.Foo'>, <type 'object'>) 

Cela signifie que super résout à une classe différente pour chaque sous-classe qu'il est appelé.Cela permet à chaque méthode de changer une petite partie de ce qui se passe et de laisser chaque autre superclasse contribuer à l'appel de la méthode, à condition qu'elle soit prête à bien jouer.

3

Outre les bonnes réponses déjà affichées, voici quelques informations supplémentaires:

  • les classes de style ancien (ceux qui ne proviennent pas de l'objet) ont un ordre méthode profondeur première résolution. Les classes à l'ancienne appellent leurs super classes comme vous en avez l'habitude.

  • Les classes de style nouveau (celles qui dérivent de l'objet) ont un ordre de résolution de méthode plus complexe. Au plus haut niveau, c'est comme la largeur en premier, mais c'est plus complexe que cela. Voir ce page pour une excellente explication. L'utilisation de "super()" permet aux nouvelles classes de style de suivre cet ordre de résolution de méthode.

  • Si vous utilisez des classes de style nouveau, vous pouvez toujours utiliser les anciennes super classes appelantes et votre code fonctionnera toujours. Les différences ne deviennent apparentes que pour des modèles d'héritage multiple plus compliqués.

Questions connexes