Super init contre parent. initialisation
une sous-classe Python peut être initialisée avec ou sans appel à super()
, comme indiqué ci-dessous
class Parent(object):
...
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
class Child(Parent):
def __init__(self):
Parent.__init__(self)
Quelle est la différence entre ces deux cas, et il est généralement préférable à l'autre?
2 réponses
le but du super est de manipuler les diamants de l'héritage. Si la classe la structure d'héritage utilise seulement l'héritage simple, puis en utilisant super () will il en résulte les mêmes appels que les appels explicites à la classe "parent".
Considérer cet héritage en diamant:
class A(object):
def __init__(self):
print('Running A.__init__')
super(A,self).__init__()
class B(A):
def __init__(self):
print('Running B.__init__')
super(B,self).__init__()
class C(A):
def __init__(self):
print('Running C.__init__')
super(C,self).__init__()
class D(B,C):
def __init__(self):
print('Running D.__init__')
super(D,self).__init__()
foo = D()
impression
Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__
tandis que si nous changeons B
B2
et utilisez des appels explicites au parent __init__
:
class B2(A):
def __init__(self):
print('Running B.__init__')
A.__init__(self)
class D2(B2,C):
def __init__(self):
print('Running D.__init__')
super(D2,self).__init__()
bar = D2()
puis la chaîne d'init appels devient
Running D.__init__
Running B.__init__
Running A.__init__
Donc, l'appel à C.__init__
est complètement ignorée.
il n'y a pas d'option privilégiée.
Si vous pouvez garantir que vous ne voulez pas en charge l'héritage multiple alors les appels parents explicites sont plus simples et plus clairs.
Si vous souhaitez soutenir l'héritage multiple, maintenant ou dans l'avenir, alors vous devez utiliser super()
. Mais comprendre qu'il y a certains écueils impliqué dans l'utilisation de super, mais avec bonne utilisation ces pièges peuvent être évités.
Le but principal de super(Child, self).__init__(self)
is permet l'initialisation correctement exécutée dans le cas d'un héritage multiple avec des structures d'héritage diamantées. Si vous appelez explicitement les constructeurs de classe de base avec un héritage multiple, certains initialiseurs peuvent être appelés deux fois. Avec un héritage unique, il n'y a pas de différence fonctionnelle entre l'utilisation de super et l'invocation explicite de la classe de base __init__()
méthode. Notez que parce que toutes les classes python nouveau style objet de la sous-classe, héritage multiple toujours implique un héritage de diamant.
super a un avantage moindre de réduire nécessite des changements si vous renommez ou changez la classe de base.
en python 3, les arguments pour super
sont optionnels, donc vous pouvez simplement faire super().__init__(self)
. Python 2 exige toujours que vous fournissiez les arguments explicitement.