2013-07-07 8 views
21

は、私が理解しようとしていたときに、正しく(2.7.35または3.xのいずれか)>>> help(super)Pythonのsuper()引数:なぜsuper(obj)ですか?

Pythonでsuper()を使用する方法をインタプリタはそれを呼び出す方法を私に語った:

class super(object) 
| super(type) -> unbound super object 
| super(type, obj) -> bound super object; requires isinstance(obj, type) 
| super(type, type2) -> bound super object; requires issubclass(type2, type) 

Python3.xでは、クラス定義内でsuper()を使用することが可能になりましたが、なぜsuper(obj)を使用できないのか分かりません。クラス定義内のsuper(self)

理由があるはずですが、見つけられません。私にとっては、これらの行はsuper(obj.__class__, obj)またはsuper(self.__class__, self)に相当し、それらは正しく動作するでしょうか?

super(obj)と入力するだけで、Python 3.xでも便利なショートカットになると思います。

+0

メタクラスで「スーパー」と呼んだときにあいまいさが出ると言いましたが、そのあいまいさも2引数形式でも存在することがわかりました。今私はよくわからない。 – user2357112

答えて

31

2つの引数を持つ形式は、Python 2でのみ必要です。その理由は、self.__class__は常に継承ツリーの "リーフ"クラス、つまりオブジェクトの最も特殊なクラスを参照しますが、 superを呼び出すと、現在どのインプリメンテーションが呼び出されているかを伝える必要があるため、継承ツリーの次のインプリメンテーションを呼び出すことができます。

は、あなたが持っていると仮定します。

class A(object): 
    def foo(self): 
     pass 

class B(A): 
    def foo(self): 
     super(self.__class__, self).foo() 

class C(B): 
    def foo(self): 
     super(self.__class__, self).foo() 

c = C() 

c.__class__は常に、Cであること。今度はc.foo()に電話するとどうなるか考えてみてください。

super(self.__class__, self)をCのメソッドで呼び出すと、super(C, self)を呼び出すようになります。これは、「Cに継承されたこのメソッドのバージョンを呼び出す」ことを意味します。それはB.fooと呼ばれ、これは問題ありません。しかし、Bからsuper(self.__class__, self)に電話をかけたときは、同じselfなのでsuper(C, self)と同じように呼びます。したがってself.__class__はまだCです。その結果、B内の呼び出しは再びB.fooを呼び出し、無限再帰が発生します。

もちろん、実際にはsuper(classThatDefinedTheImplementationThatIsCurrentlyExecuting, self)を呼び出すことができます。これは効果的にPython 3 super()の機能です。

Python 3では、ちょうどsuper().foo()を実行しても問題ありません。 super(self)がショートカットであることを意味するものは私には分かりません。 Python 2では、上記の理由でうまくいきません。 Python 3では、代わりに普通のsuper()を使うことができるので、「ロングカット」になります。

super(type)とは、Python 3では時々必要になるかもしれませんが、それは珍しい状況ではもっと難解な使い方でした。短い答えしようと

+0

同僚はもう一度別のクラスの別のメソッドに 'super'メソッドをリファクタしたので、' super(SomeOtherClass、some_obj).method(...) 'というコードが終了しました。コードを読んだ人にバグのように見えました。これは、より良い表現であったかもしれないが、終わったかもしれないが、2つの引数の「スーパー」は、いくつかのエッジケースでは依然として有用である可能性がある。 – user4815162342

+0

あなたの説明の最初の4行は私にすべてを理解させました。この例もありがとうございます。それは私が理解しようとしていた欠けている部分でした。 – Gabriel

+0

私たちは、「難解な」または「エッジ」の場合について言及し続けます。これは、葉クラスで '__init __()'をオーバーライドするときに、二重継承で二つの別々の '__init __()'関数を呼び出す必要があるときだけですか? –

0

: - 機能を実装していない、必ずしも希望クラス、

self.__class__は常にあなたのオブジェクトインスタンスの実際の(「サブ最も」)のクラスです!

super(self.__class__, self)super(__class__, self)に置き換えてください。Python 3は実装クラスにマジックセル変数__class__を提供しているため、Python 3のメソッド定義の範囲内にいます。

引数がゼロのsuper()は、すでにPython 3のsuper(__class__, self)のショートカットです。PEP3135を参照してください。

Python 2には、__class__も引数のないショートカットsuper()もありません。