web-dev-qa-db-ja.com

pythonのチェーン呼び出し親初期化子

これを考慮してください-基本クラスA、Aから継承するクラスB、Bから継承するクラスC。初期化子で親クラス初期化子を呼び出す一般的な方法は何ですか?それでもあいまいに聞こえる場合は、次のコードをご覧ください。

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()

これが今の私のやり方です。しかし、まだ一般的ではないようです。正しい型を手動で渡す必要があります。

今、私はself.__class__をsuper()の最初の引数として使用しようとしましたが、明らかにそれは機能しません-Cの初期化子に入れた場合-かなり公平に、Bの初期化子が呼び出されます。 Bで同じことを行うと、「自己」はまだCのインスタンスを指しているため、Bの初期化子を再度呼び出すことになります(これは無限再帰で終了します)。

今のところ、ダイヤモンドの継承について考える必要はありません。この特定の問題を解決することに興味があります。

273
shylent

実際にそれを行う方法は推奨されます(Python 2.xの場合)。

クラスがsuperに明示的に渡されるかどうかの問題は、機能ではなくスタイルの問題です。クラスをsuperに渡すことは、Pythonの「暗黙的よりも明示的である」という哲学に適合します。

164
dF.

Python 3には、次のような使用を可能にする改良されたsuper()が含まれています。

super().__init__(args)
187
ironfroggy

あなたは単に書くことができます:

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