問題タブ [method-resolution-order]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
python - 一般的に、Python の super() は実際にどのように機能しますか?
には、多数のポップアップが表示されるこのsuper()
素晴らしいブログ投稿や、Stack Overflow に関する多くの質問など、多くの優れたリソースがあります。ただし、最も一般的なケース (任意の継承グラフを使用) でどのように機能するか、および内部で何が行われているのかを説明するには不十分なように感じます。
次のダイヤモンド継承の基本的な例を考えてみましょう。
このようなソースからメソッド解決順序に関する Python のルールを読んだり、C3 線形化のウィキペディア ページを調べたりすると、MRO が(D, B, C, A, object)
. これはもちろん次のように確認されていD.__mro__
ます。
と
版画
これは MRO に一致します。ただし、上記のsuper(B, self).foo()
in ではB
実際に が呼び出されるC.foo
のに対し、 inb = B(); b.foo()
では単に に直行することを考慮してA.foo
ください。明らかに、使用することは、時々教えられるようにsuper(B, self).foo()
単純な近道ではありません。A.foo(self)
super()
は、その前の以前の呼び出しと、チェーンが従おうとしている全体的な MRO を明らかに認識しています。これを達成する方法は 2 つあります。super
1 つ目は、チェーン内の次のメソッドにオブジェクト自体を引数として渡すようなことですself
。このメソッドは、元のオブジェクトのように動作しますが、この情報も含みます。ただし、これは多くのことを壊すようにも思われますが (これsuper(D, d) is d
は誤りです)、少し実験することで、そうではないことがわかります。
もう 1 つのオプションは、MRO とその中の現在の位置を格納するある種のグローバル コンテキストを持つことです。のアルゴリズムsuper
は次のようになると思います。
- 現在、私たちが取り組んでいる状況はありますか? そうでない場合は、キューを含むものを作成します。クラス引数の MRO を取得し、最初の要素を除くすべての要素をキューにプッシュします。
- 現在のコンテキストの MRO キューから次の要素をポップし、
super
インスタンスの構築時にそれを現在のクラスとして使用します。 - インスタンスからメソッドにアクセスするときは
super
、現在のクラスでそれを検索し、同じコンテキストを使用して呼び出します。
ただし、これは、 への呼び出しの最初の引数として別の基本クラスを使用したり、別のメソッドを呼び出したりするなどの奇妙なことを考慮していませんsuper
。これの一般的なアルゴリズムを知りたいです。また、このコンテキストがどこかに存在する場合、それを調べることはできますか? いじってもいいですか?もちろんひどい考えですが、Python は通常、あなたが成熟した大人でなくても、成熟した大人であることを期待しています。
これにより、多くの設計上の考慮事項も導入されます。B
との関係だけを考えて書いた場合A
、後で誰かが書きC
、第三者が書いたD
場合、私のメソッドは、私が書いた時点では存在しませんでしたが、互換性のある方法でB.foo()
呼び出さなければなりません! クラスを簡単に拡張できるようにする場合は、これを説明する必要がありますが、すべてのバージョンの署名が同一であることを確認するよりも複雑かどうかはわかりません。の基本クラスのみを考慮して違いがないとしても、 の呼び出しの前後にいつコードを配置するかという問題もあります。super
C.foo()
foo
super
B
python - Python での抽象基底クラスの作成方法の違い
これらは、抽象基本クラスを作成し、具象クラスに登録するためのさまざまな方法です。
輸入品:
方法 1:
方法 2:
方法 3:
方法 4:
方法 5:
質問:
- MRO とは別に、それらの違いは何ですか?
- 使用例は異なりますか?
- それらの間でそれを行うための好ましい方法またはよりpythonicな方法はありますか?
PS: #2 のみが Python 2 でも機能することに注意してください
python - 新しいスタイル クラスで多重継承を使用する場合、実行順序はどのように決定されますか?
私はEffective Pythonの本を読んでいて、次のコードを見つけました
私が予想していた foo の値は27
( 5 * 5 + 2
) です。しかし、それはであることが判明しました35
。そして、出力は次のとおりです
MRO は理解できましたが、実行順序がわかりませんでした...TimesFiveCorrect
最初に呼び出されるべきではないですか?
python - Superで適切なPython Facadeクラスを構築していますか?
Super() を使用した多重継承のハンドルを持っていると思い、それを Facade クラス内で使用しようとしていましたが、奇妙なバグに遭遇しています。私は Fireworks と呼ばれるよくできた Python ワークフロー ソフトウェアを使用していますが、クラスとワークフロー タスクの構造はかなり厳密であるため、使いやすいように Facade クラスを作成していました。
以下は、ワークフロー タスクの基本構造です。
super
以下を使用して Facade クラスを構成しました。
これは、私を混乱させる小さな警告を除いてうまく機能します。の新しいインスタンスを作成するときBgwInput
、空のインスタンスは作成されません。以前のインスタンスで何らかの形で設定された入力セット パラメータは、新しいインスタンスに引き継がれますが、kpoints
またはではありませんqshift
。例えば:
ただし、self.__dict__['isp'] = isp
Facade クラスを変更すると、self.__dict__['isp'] = isp if isp else {}
すべてが期待どおりに動作するようです。以前のインスタンスで設定されたパラメーターは、新しいインスタンスに引き継がれません。では、Facade クラスのデフォルトが isp={} に設定されていないのはなぜですか(これが __ init __ のデフォルトである場合)。デフォルトは空白の辞書であるべきなので、以前のパラメータはどこから取得していますか?
明確にするために、Facade クラスを期待どおりに機能させるための解決策があります ( isp
Facade を に変更することによりself.__dict__['isp'] = isp if isp else {}
) が、なぜこれが必要なのかを理解しようとしています。私はsuper
、Python のメソッド解決順序に関する基本的な何かが欠けていると思います。なぜこれが起こっているのか、知識ベースを拡大しようとしていることに興味があります。
以下は、Facade クラスのメソッド解決順序です。
python - Python クラスの継承
Python の mro(メソッド解決順序) を理解するのに少し苦労しています。Python は左から右に動作します。したがって、私の理解によれば、M を呼び出す順序は次のようになります。M、B、A、Z、X、Y
しかし、呼び出しの正しい順序は次のとおりです。
誰でも順序を説明して、これを理解するのを手伝ってくれますか? ありがとうございました