私はPython2.5を実行しているので、この質問はPython 3には当てはまらない可能性があります。多重継承を使用してdiamondクラス階層を作成し、最も派生したクラスのオブジェクトを作成すると、PythonはRight Thing(TM)を実行します。最も派生したクラスのコンストラクターを呼び出し、次に左から右にリストされている親クラス、次に祖父母を呼び出します。私はPythonのMROに精通しています。それは私の質問ではありません。スーパーから返されたオブジェクトが実際に親クラスのスーパーの呼び出しに正しい順序で通信する方法に興味があります。このサンプルコードを考えてみましょう。
#!/usr/bin/python
class A(object):
def __init__(self): print "A init"
class B(A):
def __init__(self):
print "B init"
super(B, self).__init__()
class C(A):
def __init__(self):
print "C init"
super(C, self).__init__()
class D(B, C):
def __init__(self):
print "D init"
super(D, self).__init__()
x = D()
コードは直感的なことを行い、次のように出力します。
D init
B init
C init
A init
ただし、Bのinit関数でsuperの呼び出しをコメントアウトすると、AもCのinit関数も呼び出されません。これは、Bのsuperへの呼び出しが、クラス階層全体におけるCの存在を何らかの形で認識していることを意味します。superはオーバーロードされたget演算子でプロキシオブジェクトを返すことを知っていますが、Dのinit定義でsuperによって返されるオブジェクトは、Bのinit定義でsuperによって返されるオブジェクトにCの存在をどのように伝えますか?その後のスーパーユースの呼び出しで得られる情報は、オブジェクト自体に保存されていますか?もしそうなら、なぜスーパーではなくself.superではないのですか?
編集:Jekkeは、superはクラスのインスタンスではなく、クラスの属性であるため、self.superではないことを非常に正しく指摘しました。概念的にはこれは理にかなっていますが、実際にはスーパーもクラスの属性ではありません!これは、BがAから継承する2つのクラスAとBを作成し、を呼び出すことによって、インタープリターでテストできますdir(B)
。super
または__super__
属性はありません。