2017-10-07 14 views
2

次の例では、CL2のsuperを「cl2 test cl5」のself.test()に置き換えると、同じ出力が得られます。どのようにしてスーパーが差をつけるのか。pythonのsuperは冗長ですか?

class CL1(object): 
    def test(self): 
     print "test cl1" 

class CL2(CL1): 
    def abc(self): 

     print "in cl2" 
     super(CL2,self).test() 
     #self.test() 

class CL3(CL1): 
    def test(self): 
     print "test cl3" 

class CL5(CL1): 
    def test(self): 
     print "test cl5" 

class CL4(CL2,CL5,CL3): 
    def add(self): 
     print 'cl4' 

def main() 
    o=CL4() 
    o.abc() 
if __name__ == "__main__": 

    main() 
+0

興味深い質問です。 「オブジェクト」以外のオブジェクトをサブクラス化するときは、絶対に必要です。 –

+0

'super'は誤って命名されました。それは必ずしもそれが使用されているクラスの(単一の)静的に定義された親クラスを参照するとは限りません。 – chepner

答えて

2

あなたは、クラスCL2の内側に、それは暗黙的にその親(CL1)のtest()メソッドを呼び出します、superを使用していない場合。

しかし、CL2クラスもtest()というメソッドを定義すると、あいまいな問題が発生します(これはOOPでメソッドオーバーライドと呼ばれます)。デフォルトでは現在のクラスのtest()メソッドが使用されていますが、代わりに親クラスのメソッドを呼び出す場合は、メソッドを明示的に呼び出すときにsuperを使用する必要があります。

は、この図を考えてみましょう:

class CL1(object): 
    def test(self): 
     print "test CL1" 

class CL2(CL1): 
    def test(self): 
     print "test CL2" 

    def abc(self): 

     print "in CL2" 
     super(CL2,self).test() 
     self.test() 

o=CL2() 
o.abc() 

ウィル出力:

in CL2 
test CL1 
test CL2 
+0

ここで 'super'は必要ありません。 CL1.test(self)を明示的に簡単に呼び出すことができます。 – chepner

+0

はい。 chepnerありがとう。知っている。しかし、クラス「CL1」の名前が変更されたらどうなるでしょうか? –

+0

名前を変更すると、その名前も変更できます。もしあなたが 'super'を使っていればもっと便利ですが、*必須ではありません。なぜ' super'が追加されたのかは分かりません。 – chepner

-2

superは、あなたの子供クラスのメソッドのうち、基底クラスの名前を残すためだけの利便性ではありません。 cooperative継承のために設計されています。このクラスでは、適切に設計されたクラスが、C3リニアライゼーションアルゴリズムに従って、正しい順序でオーバーライドされたメソッドを呼び出します。

superは、定義しているクラスの静的に宣言された親を必ずしも参照しているとは限りません。あなたがを実行したときに

class A: 
    def foo(self): 
     print("A.foo") 

class B(A): 
    def foo(self): 
     print("B before super") 
     super().foo() 
     print("B.foo") 

class C(A): 
    def foo(self): 
     print("C before super") 
     super().foo() 
     print("C.foo") 

class D(B, C): 
    def foo(self): 
     print("D before super") 
     super().foo() 
     print("D.foo") 

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

コールsuper().foo()B.foo内部A.fooを呼び出すことはありません。次のコードを考えてみましょう代わりにCがの直後にあり、Dのメソッド解決順序(MRO)になるため、C.fooが実行されます。

すぐA.fooを呼び出す常にB.fooないでOKでない場合は、関係なく、selfのタイプの、superを使用しないでください。 superを使用することにより、サポートするように設計されたセマンティクスに同意しており、メソッドをsuperとして文書化する必要があります。それ以外の場合は、代わりにA.foo(self)を使用し、ではないことをで示します。superを使用してください。