ホームページ > バックエンド開発 > Python チュートリアル > Python の新しい多重継承アルゴリズム C3 の紹介

Python の新しい多重継承アルゴリズム C3 の紹介

WBOY
リリース: 2016-06-16 08:41:32
オリジナル
1107 人が閲覧しました

mro はメソッド解決順序 (メソッド解釈順序) であり、主に多重継承時に属性のパス (どのクラスから来たのか) を決定するために使用されます。

python2.2バージョンでは、アルゴリズムの基本的な考え方は、検索されたクラスを含む各祖先クラスの継承構造に基づいてリストを作成し、戦略に従って重複を削除することです。しかし、単調性(逐次保存)を維持できないため、バージョン2.3からは新しいアルゴリズムC3が採用されました。

C3 アルゴリズムを使用する理由

C3 アルゴリズムは最初に Lisp 用に提案されました。元の深さ優先検索アルゴリズムがローカル優先度と単調性を満たさないという問題を解決するために Python に適用されました。

ローカル優先度: C(A,B) など、宣言時の親クラスの順序を指します。クラス C オブジェクトのプロパティにアクセスする場合は、最初にクラス A を検索し、次にクラスを検索する必要があります。宣言の順序に従ってB。

単調性: C の解析順序で A が B より前にランクされている場合、この順序は C のすべてのサブクラスでも満たされる必要があります。

C3 アルゴリズム

mro を決定するには、まず線形シーケンスを決定する必要があります。次に、シーケンス内のクラスの順序によって検索パスが決定されます。したがって、C3 アルゴリズムは線形シーケンスを生成します。

基本クラスから継承する場合:

コードをコピー コードは次のとおりです:

クラスB(A)

このとき、B の mro シーケンスは [B,A]

複数の基本クラスから継承する場合

コードをコピー コードは次のとおりです:

クラス B(A1,A2,A3 ...)

このとき、B の mro シーケンス mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])
マージ操作は C3 アルゴリズムの中核です。

シーケンスの最初の要素が他のシーケンスの最初の要素である場合、または他のシーケンスに表示されない場合は、マージ操作を実行するすべてのシーケンスからこの要素を削除し、マージします。ミスターの現在のもの。

マージ操作後のシーケンスは、マージ操作のシーケンスが空になるまでマージ操作を実行し続けます。

マージ操作のシーケンスを空にできない場合、それは不正であることを意味します。

例:

コードをコピー コードは次のとおりです:

クラス A(O):パス
クラス B(O):パス
クラス C(O):pass
クラス E(A,B):pass
クラス F(B,C):pass
クラス G(E,F):pass

A、B、および C はすべて基本クラスから継承するため、mro シーケンスは [A,O]、[B,O]、[C,O] となります

コードをコピー コードは次のとおりです:

mro(E) = [E] + merge(mro(A), mro(B), [A,B])
= [E] + マージ([A,O], [B,O], [A,B])

マージ操作を実行するシーケンスは [A,O]、[B,O]、[A,B] です。

A はシーケンス [A, O] の最初の要素ですが、シーケンス [B, O] には現れず、シーケンス [A, B] の最初の要素でもあるため、マージ操作が実行されます。([A,O]、[B,O]、[A,B]) から A を削除し、現在の mro、[E] にマージします。
mro(E) = [E,A] + merge([O], [B,O], [B])

マージ操作を再度実行します。O はシーケンス [O] の最初の要素ですが、O はシーケンス [B, O] にあり、最初の要素ではありません。引き続き、[B, O] の最初の要素 B に注目します。B は条件を満たすため、マージ操作が実行されるシーケンスから B が削除され、[E, A] にマージされます。

コードをコピー コードは次のとおりです:

mro(E) = [E,A,B] + merge([O], [O])
= [E,A,B,O]

C3 アルゴリズムを実装するコード

コードをコピー コードは次のとおりです:

#-*- エンコーディング:GBK -*-#
def mro_C3(*cls):
        if len(cls)==1:
            そうでない場合は cls[0].__bases__:
                return cls
            それ以外:
                return cls+ mro_C3(*cls[0].__bases__)
        それ以外:
            seqs = [list(mro_C3(C)) for C in cls ] +[list(cls)]
            res = []
            True の場合:
              non_empty = list(filter(None, seqs))
              non_empty でない場合:
                  タプルを返す (res)
              non_empty のシーケンス:
                  候補 = seq[0]
                  not_head = [s for s in non_empty if 候補 in s[1:]]
                  if not_head:
                      候補者 = なし
                  それ以外:
                      休憩
              候補でない場合:
                  raise TypeError("一貫性のない階層、C3 MRO は不可能です")
              res.append(候補)
              non_empty のシーケンス:
                  if seq[0] == 候補:
                      デルシーク[0]

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート