ホームページ  >  記事  >  バックエンド開発  >  Python プログラミングにおける super キーワードの使用法の詳細な分析

Python プログラミングにおける super キーワードの使用法の詳細な分析

WBOY
WBOYオリジナル
2016-07-06 13:29:451430ブラウズ

公式ドキュメントでは、super の定義については詳しく説明されていません。これは、大まかに言うと、いくつかの継承されたメソッドを呼び出すことができるようにするための、最も一般的に使用される状況です。次の例:

リーリー

サブクラス C は、親クラス B の同名のメソッドを書き換えます。上書き実装では、スーパーによってインスタンス化されたプロキシ オブジェクトを通じて、親クラスの同名のメソッドが呼び出されます。

スーパークラスの初期メソッドシグネチャは次のとおりです:

リーリー

self を除く 1 つまたは 2 つのパラメータを受け入れます。注釈で述べたように、2 つのパラメータを受け入れる場合、バインドされたスーパー インスタンスが返されます。2 番目のパラメータが省略された場合は、バインドされていないスーパー オブジェクトが返されます。

通常の状況では、継承されたクラスメソッドまたは静的メソッドを呼び出す場合、現時点では super(type, type2).some_method を使用することで目的を達成できます。 obj) がこの場合に使用されます。スーパー オブジェクトには、カスタム実装された getattribute メソッドも使用できます。ただし、後者は通常、インスタンス メソッドの呼び出しに使用されるため、メソッドを検索するときに、対応するインスタンスを渡してバインドされたインスタンス メソッドを取得できます。

リーリー
スーパー オブジェクトを初期化する場合、渡される 2 番目のパラメーターは実際にはバインドされたオブジェクトです。上の例の場合のように、最初のパラメーターはマーク検索の開始点として理解できます: super(B, b)。 B 自体を除く B.__mro__ にリストされているクラスでメソッド test が見つかります。メソッドは非データ記述子であるため、スーパー オブジェクトのカスタム get 属性は実際には A.__dict['test' ].__get__(b) に変換されます。 、B)。

Super は多くの場所で使用され、指定された型をハードコーディングすることなくプログラムをより動的にするだけでなく、カスタム型を生成するためにベースクラスで new を見つけるためにメタクラスで super を使用するなど、他の特定の場所でも使用する必要があります。テンプレート; カスタム内 属性を取得する際の無限ループなどを防ぐために使用されます。

スーパーについては、Python 記述子と一緒に理解することをお勧めします。スーパーは記述子プロトコルを実装し、非データ記述子であるためです。これは、誰もがスーパーの使用法と動作原理をよりよく理解するのに役立ちます。

同時に、次の 4 つの点に注意してください:


1. 単一継承では、super() と __init__() によって実装される関数は似ています

リーリー
出力結果:

リーリー

super() 継承を使用する場合、基本クラスを明示的に参照する必要はありません。

2. super() は新しいスタイルのクラスでのみ使用できます

基底クラスを古いスタイルのクラスに変更します。つまり、基底クラスを継承しません

リーリー
実行すると、bの初期化時にエラーが報告されます:

リーリー

3. Super は親クラスではなく、継承シーケンスの次のクラスです

多重継承の場合、次の関数と同様に、super() は継承順序で親クラスではなく次のクラスを返すことと同等です。

リーリー

mro() はクラスの継承順序を取得するために使用されます。

例:

リーリー

入力結果は以下の通りです:

リーリー

supder と親クラスの間には関係がないため、実行順序は A —> B—>—> Base になります

実行プロセスは以下と同等です: childC() を初期化するとき、最初に super(childA, self) を呼び出します。childA のコンストラクターで __init__() は、継承順序で childA の後のものを返します。現在のクラス childB; 次に childB().__init()__ を実行し、この順序で続行します。

多重継承において、childA() の super(childA, self).__init__() を Base.__init__(self) に置き換えると、実行時、childA を継承した後、省略された Base クラスに直接ジャンプします。子供B:

リーリー

super() メソッドから、super() の最初のパラメーターは継承チェーン内の任意のクラスの名前にできることがわかります。

それ自体の場合、順番に次のクラスを継承します

継承チェーン内の前のクラスの場合、無限に再帰されます

継承チェーンの後のクラスの場合、継承チェーンの概要自体と受信クラスの間のクラスは無視されます。

たとえば、childA() の super を super(childC, self).__init__() に変更すると、プログラムは無限に再帰的に実行されます。

次のような:

リーリー

4. super() の繰り返し呼び出しを回避できます

childA が Base に基づいている場合、childB は childA と Base を継承し、childB が Base の __init__() メソッドを呼び出す必要がある場合、 __init__() が 2 回実行されます。 リーリー

リーリー

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。