ホームページ  >  記事  >  バックエンド開発  >  Pythonプログラミングにおけるスーパー関数の正しい理解と使い方分析

Pythonプログラミングにおけるスーパー関数の正しい理解と使い方分析

PHP中文网
PHP中文网オリジナル
2016-07-22 08:56:362031ブラウズ

Python2.2以前では、サブクラスが親クラスのメソッドを呼び出す必要がある場合、クラス名を使用して直接クラスのメソッドを呼び出し、つまり非バインドクラスメソッドを呼び出し、自身のオブジェクトselfを渡していました。パラメータとして。

class A(object): 
  def say(self): 
    print 'I am A' 
 
class B(A): 
  def say(self): 
    print 'I am B' 
    A.say(self) 
 
b = B() 
b.say()

Output

I am B
I am A

これはうまく機能しますが、親クラスの名前を変更すると、親クラスへの明示的な呼び出しを 1 つずつ修正する必要があります。子クラス 親クラスとの結合度が比較的高いクラスです。
そのため、ハードコーディングを回避し、親クラスの名前を気にする必要がないように、Python 2.2 の後に super() 関数が導入されました。
super() 関数を使用すると、上記のコードは次のように記述できます。

class B(A): 
  def say(self): 
    print 'I am B' 
    super(B,self).say()

python3.0 以降、super() 関数はパラメーターを渡す必要がありません。つまり、上記のコード行を直接 super().say() にすることができます。

注意事項:

  • super は、新しいスタイルのクラスでのみ使用できます。

  • Super には多重継承の問題があります。サブクラスが複数の親クラスを継承する場合、super は最初の親クラスのメソッドを呼び出します。

  • 親クラスメソッドを呼び出すこれら 2 つの方法を混合しないでください。アンバインド クラス メソッドを使用するか、両方ともスーパーを使用してください。そうしないと、呼び出されないか、複数回呼び出される可能性があります。

しかし:
スーパーについて考えるときに親クラスを考えないでください! super は MRO の次のクラスを指します。
スーパーというと親クラスを思い出しますが、これは初心者が犯しやすい間違いであり、当時の私も犯した間違いでした。

def super(cls, inst):
  mro = inst.__class__.mro()
  return mro[mro.index(cls) + 1]

2 つのパラメーター cls と inst はそれぞれ次の 2 つのことを行います:
1. inst は、cls を通じて現在の MRO 内のインデックスを検索し、mro[index + 1] を返します。 】
この2つはスーパーの本質です、必ず覚えておいてください!

MRO は Method Resolution Order の略で、クラスの継承順序を表します。

例:

class Root(object):
  def __init__(self):
    print("this is Root")

class B(Root):
  def __init__(self):
    print("enter B")
    # print(self) # this will printsuper(B, self).__init__()
    print("leave B")

class C(Root):
  def __init__(self):
    print("enter C")
    super(C, self).__init__()
    print("leave C")

class D(B, C):
  pass

d = D()
print(d.__class__.__mro__)

Output

enter B
enter C
this is Root
leave C
leave B
(,,,,)

super が親クラスと実際の関係を持たないことがわかった後は、enter B の次の文が次の文である理由を理解するのは難しくありません。 this is Root の代わりに C を入力します (super が「親クラスのメソッドを呼び出す」ことを意味すると考えると、次の文は this is Root になるはずだと自然に考えるでしょう)。このプロセスは、B の __init__ 関数で次のようになります。

super(B, self).__init__()

まず、self.__class__.__mro__ を取得します。ここでの self は、B のインスタンスではなく D のインスタンスであることに注意してください。 B MRO 内のインデックスを見つけて、次のインデックスを見つけます。明らかにBの次はCです。そこで、C の __init__ を呼び出し、enter C と入力します。

ところで、なぜ B の __init__ が呼び出されるのか: D は __init__ を定義していないため、MRO 内の次のクラスを見つけて __init__ が定義されているかどうかを確認します。つまり、B の __init__ を呼び出します。

(実際、これらすべてのロジックはまだ非常に明確です。重要なのは、super が何を行うかを理解することです。

上記は、Python プログラミングにおけるスーパー関数の正しい理解と使用法分析です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。


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