2953

の使用法を理解しようとしていますsuper()。その外観から、両方の子クラスを作成できます。

次の2つの子クラスの実際の違いについて知りたいです。

class Base(object):
    def __init__(self):
        print "Base created"

class ChildA(Base):
    def __init__(self):
        Base.__init__(self)

class ChildB(Base):
    def __init__(self):
        super(ChildB, self).__init__()

ChildA() 
ChildB()
4

7 に答える 7

2148

super()基本クラスを明示的に参照することを避けることができます。これは便利です。しかし、主な利点は、あらゆる種類の楽しいことが起こり得る多重継承にあります。まだ見ていない場合は、superの標準ドキュメントを参照してください。

Python 3.0 で構文が変更されたことに注意してください。super().__init__()代わりに、super(ChildB, self).__init__()どちらの IMO の方がかなり優れているかを言うことができます。標準ドキュメントは、非常に説明的な使用ガイドも参照しています。super()

于 2009-02-23T00:37:31.220 に答える
270

Python 3.0+では使用できることが注目されています

super().__init__()

これは簡潔であり、親またはクラス名を明示的に参照する必要がないため、便利です。Python 2.7以下で追加したいのですself.__class__が、クラス名の代わりに書くことで、名前を区別しない動作を実装する人もいます。

super(self.__class__, self).__init__()  # DON'T DO THIS!

ただし、これにより、子クラスを返す可能性superのあるクラスから継承するクラスの呼び出しが中断されます。self.__class__例えば:

class Polygon(object):
    def __init__(self, id):
        self.id = id

class Rectangle(Polygon):
    def __init__(self, id, width, height):
        super(self.__class__, self).__init__(id)
        self.shape = (width, height)

class Square(Rectangle):
    pass

ここにSquare、 のサブクラスである クラス がありRectangleます。SquareforのコンストラクターでRectangle十分なため、別のコンストラクターを作成したくないとしますが、何らかの理由で Square を実装して、他のメソッドを再実装できるようにしたいとします。

Squareusingを作成すると、独自のコンストラクターを指定していないためmSquare = Square('a', 10,10)、Python はコンストラクターを呼び出します。ただし、 のコンストラクターでは、呼び出しは のスーパークラスを返すため、コンストラクターを再度呼び出します。@S_Cで言及されているように、これが無限ループの発生方法です。この場合、実行時にコンストラクターを呼び出していますが、引数を指定しないため、エラーが発生します。RectangleSquareRectanglesuper(self.__class__,self)mSquareRectanglesuper(...).__init__()Rectangle

于 2013-10-08T20:08:39.057 に答える
82

スーパーには副作用がありません

Base = ChildB

Base()

期待どおりに動作します

Base = ChildA

Base()

無限再帰に入ります。

于 2012-11-27T23:26:47.940 に答える
74

ちょっと注意してください...Python2.7で、バージョン2.2で導入されて以来、親の1つが最終的に継承するクラス(新しいスタイルのクラスsuper())から継承する場合にのみ呼び出すことができると思います。super()object

個人的には、Python 2.7コードについては、BaseClassName.__init__(self, args)実際にを使用できるようになるまで使用を続けsuper()ます。

于 2012-05-25T17:52:49.797 に答える
57

本当にありません。super()MROの次のクラス(メソッド解決順序、でアクセスcls.__mro__)を調べて、メソッドを呼び出します。__init__ベースを呼び出すだけでベースが呼び出されます__init__。たまたま、MROにはベースという1つのアイテムしかありません。したがって、実際にはまったく同じことを行っていますが、より良い方法でsuper()(特に、後で多重継承に入る場合)。

于 2009-02-23T00:34:57.840 に答える
37

主な違いは、ChildA.__init__が無条件に呼び出されるのBase.__init__に対し、 の祖先の行でたまたま祖先でChildB.__init__あるクラスが呼び出さ__init__れる ことです (これは、予想とは異なる場合があります)。ChildBself

ClassC多重継承を使用するを追加する場合:

class Mixin(Base):
  def __init__(self):
    print "Mixin stuff"
    super(Mixin, self).__init__()

class ChildC(ChildB, Mixin):  # Mixin is now between ChildB and Base
  pass

ChildC()
help(ChildC) # shows that the Method Resolution Order is ChildC->ChildB->Mixin->Base

thenはforインスタンスBaseの親ではなくなりました。ChildBがインスタンスである場合を指しChildCます。super(ChildB, self)MixinselfChildC

Mixinと の間ChildBに挿入しましたBase。そして、あなたはそれを利用することができますsuper()

したがって、共同多重継承シナリオで使用できるようにクラスを設計している場合はsuper、実行時に誰が祖先になるか本当にわからないため、クラスを使用します。

スーパーと考えられているスーパーポストと pycon 2015 付属のビデオ、これをかなりよく説明しています。

于 2015-09-21T06:41:03.070 に答える