web-dev-qa-db-ja.com

多重継承はsuper()および異なる__init __()引数でどのように機能しますか?

私はいくつかのより高度なpython主題に飛び込んでいます(少なくとも私には高度です)。私は今、多重継承とsuper()の使用方法について読んでいます。スーパー関数の使用方法を理解しますが、(1)このように実行することの何が問題になっていますか?:

_class First(object):
    def __init__(self):
        print "first"

class Second(object):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        First.__init__(self)
        Second.__init__(self)
        print "that's it"
_

Super()について、 AndrewKuchlingsのPython Warts に関する論文は次のように述べています。

派生クラスが複数の基本クラスから継承し、それらの一部またはすべてにinitメソッドがある場合も、super()の使用法は正しくなります。

したがって、上記の例を次のように書き直しました。

_class First(object):
    def __init__(self):
        print "first"

class Second(object):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__(self)
        print "that's it"
_

ただし、これは、Firstにある最初のinitのみを実行します。 (2)super()を使用して、FirstSecondの両方のinitを実行できますか?その場合、どのように実行しますか?super(Third, self).__init__(self)を2回実行すると、First。init()が2回実行されます。

さらに混乱を加えるため。継承されたクラスのinit()関数が異なる引数を取る場合はどうなりますか。たとえば、次のようなものがある場合はどうなりますか。

_class First(object):
    def __init__(self, x):
        print "first"

class Second(object):
    def __init__(self, y, z):
        print "second"

class Third(First, Second):
    def __init__(self, x, y, z):
        First.__init__(self, x)
        Second.__init__(self, y, z)
        print "that's it"
_

(3)super()を使用して、さまざまな継承クラスのinit関数に関連する引数を提供するにはどうすればよいですか?

すべてのヒントは大歓迎です!

ps。いくつか質問があるので、太字にして番号を付けました。

28
kramer65

質問2の場合、各クラスでsuperを呼び出す必要があります。

class First(object):
    def __init__(self):
        super(First, self).__init__()
        print "first"

class Second(object):
    def __init__(self):
        super(Second, self).__init__()
        print "second"

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print "that's it"

質問3の場合、それは実行できません。メソッドには同じ署名が必要です。ただし、親クラスの一部のパラメーターを無視するか、キーワード引数を使用することができます。

12
Guillaume

1)1で行ったように行うことには何の問題もありません。基本クラスの属性を使用する場合は、基本クラスを呼び出す必要がありますinit()、またはメソッドを使用している場合でも独自のクラスの属性を使用する基本クラスから、基本クラスを呼び出す必要がありますinit()

2)pythonはMRO(メソッド解決順序)を使用するため、superを使用してFirstとSecondの両方のinitを実行することはできません。

次のコードを参照してくださいこれはダイヤモンド階層です

class A(object): 
    def __init__(self):
        self.a = 'a'
        print self.a

class B(A):
    def __init__(self):
        self.b = 'b'
        print self.b

class C(A):
    def __init__(self):
        self.c = 'c'
        print self.c

class D(B,C):
    def __init__(self):
        self.d = 'd'
        print self.d
        super(D, self).__init__()

d = D()
print D.mro()

印刷します:

d
b
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]

pythonのMROはD、B、C、Aになります

bにinitメソッドがない場合は、Cになります。

3)すべてのメソッドが同じ署名を持つ必要があることを行うことはできません。

2
Vb407