web-dev-qa-db-fra.com

Initialisation des appels parent en chaîne dans python

Considérez ceci - une classe de base A, une classe B héritant de A, une classe C héritant de B. Quel est un moyen générique d'appeler un initialiseur de classe parent dans un initialiseur? Si cela semble encore trop vague, voici du code.

class A(object):
    def __init__(self):
        print "Initialiser A was called"

class B(A):
    def __init__(self):
        super(B,self).__init__()
        print "Initialiser B was called"

class C(B):
    def __init__(self):
        super(C,self).__init__()
        print "Initialiser C was called"

c = C()

Voici comment je le fais maintenant. Mais cela semble encore un peu trop générique - vous devez toujours passer un type correct à la main.

Maintenant, j'ai essayé d'utiliser self.__class__ comme premier argument de super (), mais, évidemment, cela ne fonctionne pas - si vous le mettez dans l'initialiseur pour C - assez bien, l'initialiseur de B est appelé. Si vous faites la même chose dans B, "self" pointe toujours sur une instance de C et vous appelez à nouveau l'initialiseur de B (cela aboutit à une récursion infinie).

Inutile de penser à la transmission des diamants pour le moment, je souhaite simplement résoudre ce problème spécifique.

276
shylent

La façon dont vous le faites est bien celle recommandée (pour Python 2.x).

La question de savoir si la classe est passée explicitement à super est une question de style plutôt que de fonctionnalité. Passer la classe à super correspond à la philosophie de Python selon laquelle "explicite vaut mieux qu'implicite".

164
dF.

Python 3 inclut un super () amélioré qui permet une utilisation comme celle-ci:

super().__init__(args)
191
ironfroggy

Vous pouvez simplement écrire:

class A(object):

    def __init__(self):
        print "Initialiser A was called"

class B(A):

    def __init__(self):
        A.__init__(self)
        # A.__init__(self,<parameters>) if you want to call with parameters
        print "Initialiser B was called"

class C(B):

    def __init__(self):
        # A.__init__(self) # if you want to call most super class...
        B.__init__(self)
        print "Initialiser C was called"
25
Jay Parikh