ホームページ  >  記事  >  バックエンド開発  >  Python の多重継承におけるダイヤモンド継承

Python の多重継承におけるダイヤモンド継承

angryTom
angryTom転載
2020-02-12 12:45:034082ブラウズ

この記事では、Python の多重継承におけるダイヤモンド継承の使い方を紹介します。これから Python を学習する友人の参考になれば幸いです。

Python の多重継承におけるダイヤモンド継承

継承はオブジェクト指向プログラミングの重要な方法であり、継承を通じてサブクラスは親クラスの機能を拡張できます。 Python では、クラスは複数の親クラスから継承することができ、これを Python の 多重継承 (多重継承) と呼びます。

構文

class SubclassName(BaseClass1, BaseClass2, BaseClass3, ...):
    pass

ひし形の継承

推奨学習: Python ビデオ チュートリアル

複数レベルでの継承多重継承と併用すると、多重継承など複雑な継承関係が現れます。

その中に、ダイヤモンドの継承が登場します。以下に示すように。 Python の多重継承におけるダイヤモンド継承

この構造では呼び出し順序に疑問があります。呼び出し順序は次のどれですか?

  • D-> B-> A->C (深さ優先)
  • D->B->C->A (幅優先)

答えてみましょうこの質問。

例を見てみましょう:

class A():
    def __init__(self):
        print('init A...')
        print('end A...')

class B(A):
    def __init__(self):
        print('init B...')
        A.__init__(self)
        print('end B...')

class C(A):
    def __init__(self):
        print('init C...')
        A.__init__(self)
        print('end C...')

class D(B, C):
    def __init__(self):
        print('init D...')
        B.__init__(self)
        C.__init__(self)
        print('end D...')

if __name__ == '__main__':
    D()

出力結果

init D...
init B...
init A...
end A...
end B...
init C...
init A...
end A...
end C...
end D...

出力結果からの呼び出しシーケンスは次のとおりです: D->B->A->C ->A. B と C が共同で A を継承し、A が 2 回呼び出されていることがわかります。 A を 2 回呼び出す必要はありません。

実は、上記の問題の根本原因はすべて MRO に関係しています。MRO (Method Resolution Order)Method Resolution Order とも呼ばれ、主に使用されます。多重継承時の解決を決定します。属性はどのクラスから来ますか? C3 というアルゴリズムを使用します。基本的な考え方は、 は幅を最初に使用し、左から右へ、同じクラスが複数回呼び出される場合、必要なプロパティとメソッドを見つけるための原則。

それでは、最上位の親クラスのメソッドが複数回呼び出されるのを防ぐにはどうすればよいでしょうか? この時点では Super() が必要です。Super は本質的に MRO 情報を内部的に記録するクラスです。 C3 アルゴリズムでは、同じクラスが 1 回だけ検索されるようにするため、最上位の親クラスのメソッドが複数回実行されるのを回避できます。上記のコードは次のように変更できます。

class A():
    def __init__(self):
        print('init A...')
        print('end A...')

class B(A):
    def __init__(self):
        print('init B...')
        super(B, self).__init__()
        print('end B...')

class C(A):
    def __init__(self):
        print('init C...')
        super(C, self).__init__()
        print('end C...')

class D(B, C):
    def __init__(self):
        print('init D...')
        super(D, self).__init__()
        print('end D...')

if __name__ == '__main__':
    D()

出力結果:

init D...
init B...
init C...
init A...
end A...
end C...
end B...
end D...

このときの呼び出し順序は、D->B->C->A であることがわかります。つまり、breadth-first トラバーサル方法が使用されます。

補足内容

Pythonのクラスは、classicクラスと呼ばれるクラスと、new styleクラスと呼ばれるクラスの2種類に分けられます。どちらも多重継承をサポートしていますが、継承の順序が異なります。

  • 新しいスタイル クラス: オブジェクトから継承されたクラス。 (例: class A(object))。breadth-first 検索 (つまり、最初に水平方向の検索、次に上方向の検索) を使用して継承されます。
  • クラシック クラス: オブジェクトを継承しないクラス。 (例: class A())、 Depth-first 検索メソッドを使用して継承します (つまり、最初に継承ツリーの左側に深く入り、次に戻り、右側を見つけます)。

Python 2.x には、クラシック クラスと新しいクラスの 2 種類のクラスがあります。 Python3.x には新しいスタイルのクラスがたくさんあります。

その他の Python 関連のチュートリアルについては、Python チュートリアル 列に注目してください。

以上がPython の多重継承におけるダイヤモンド継承の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。