madokaのブログ

勉強したことのoutput先として使ってます。内容はpythonがらみが多いかもです。

多重継承において取得できるメソッドやプロパティはどれ?

pythonでは多重継承ができます。もし同じメソッド、プロパティを持つクラス2つを継承した場合、どちらが取得できるのでしょうか。

下記にこれを検証するプログラムを書きました。

クラス名 継承順番 初期化順番
C A, B A, B
D B, A A, B
E A, B B, A

このようにクラスを作り、継承の順番、初期化順番によって取得できるメソッド、プロパティがどのように変わるか検証します。

class A:
    def __init__(self):
        self.text = "a"

    def say_class_name(self):
        print("A")


class B:
    def __init__(self):
        self.text = "b"

    def say_class_name(self):
        print("B")


class C(A, B):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)

    def print(self):
        self.say_class_name()
        print(self.text)


class D(B, A):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)

    def print(self):
        self.say_class_name()
        print(self.text)


class E(A, B):
    def __init__(self):
        B.__init__(self)
        A.__init__(self)

    def print(self):
        self.say_class_name()
        print(self.text)


if __name__ == '__main__':
    C().print()
    print("----")
    D().print()
    print("----")
    E().print()

これを起動すると以下のように出力が得られます。

A
b
----
B
b
----
A
a

C, Dについて継承する順番を変えたところ、利用しているメソッドが変化しました。このことから優先されるメソッドは、継承の順番で先に書いたものであることがわかります。

C, Eについて初期化する順番を変えたところ、メソッドは変わらなかったがプロパティが最後に書かれたものが取得できました。このことからプロパティについては上書きという考え方が適切でしょう。


ちなみにinitを書かないとB -> A の順で初期化を行なっていることが下記より確認できました。

class C(A, B):
    def print(self):
        self.say_class_name()
        print(self.text)
        
if __name__ == '__main__':
    C().print()
A
a

まとめ

  • プロパティは初期化する順番によって変わり、後に初期化した方が優先されます。デフォルトでは継承した順番で先の方が後に初期化するようになっていそうです。
  • メソッドについては、継承した順番によって変わります。先に継承したものが優先されるようです。