次の基本クラスとサブクラスがあります。
class Event(object):
def __init__(self, sr1=None, foobar=None):
self.sr1 = sr1
self.foobar = foobar
self.state = STATE_NON_EVENT
# Event class wrappers to provide syntatic sugar
class TypeTwoEvent(Event):
def __init__(self, level=None):
self.sr1 = level
self.state = STATE_EVENT_TWO
さらに私のコードで、私はTypeTwoEvent
クラスのインスタンスを検査して、基本クラスに存在することがわかっているフィールドをチェックしています-デフォルトで値None
になると思っていました。ただし、私のコードでは次の例外が発生します。
AttributeError: 'TypeTwoEvent'オブジェクトに属性 'foobar'がありません
基本クラスのフィールドはサブクラスによって継承され、サブクラスのインスタンスを作成すると基本クラスがインスタンス化される(つまり、そのコンストラクターが呼び出される)という印象を受けました...
ここで何が欠けていますか? TypeTwoEvent
にfoobar
属性がないのはなぜですか-派生元の基本クラスにfoobar
属性がある場合
サブクラスは次のようになります。
class TypeTwoEvent(Event):
def __init__(self, level=None, *args, **kwargs):
super(TypeTwoEvent, self).__init__(*args, **kwargs)
self.sr1 = level
self.state = STATE_EVENT_TWO
__init__
メソッドをオーバーライドするため、親の動作を実行する場合は親メソッドを呼び出す必要があります。
__init__
は、その奇妙な名前に反して特別な方法ではないことを覚えておいてください。これは、オブジェクトの作成後に自動的に呼び出されるメソッドです。それ以外の場合は通常のメソッドであり、通常の継承ルールが適用されます。
super(ClassName, self).__init__(arguments, that, goes, to, parents)
メソッドの親バージョンを呼び出す構文です。
*args
と**kwargs
の場合、子メソッドのシグネチャがそれを行わず、親が必要とするため、__init__
に渡されるすべての追加の引数をキャッチし、それを親メソッドに渡すことが保証されます。これらの引数は機能します。
親クラスのコンストラクター(___init__
_)をオーバーライドしています。それを拡張するには、親のコンストラクタを super()
呼び出しで明示的に呼び出す必要があります。
_class TypeTwoEvent(Event):
def __init__(self, level=None, **kwargs):
# the super call to set the attributes in the parent class
super(TypeTwoEvent, self).__init__(**kwargs)
# now, extend other attributes
self.sr1 = level
self.state = STATE_EVENT_TWO
_
super
呼び出しは常にサブクラスの___init__
_メソッドの先頭にあるnotであることに注意してください。その場所は、状況とロジックによって異なります。
インスタンスが作成されると、その__init__
メソッドが呼び出されます。この場合、それはTypeTwoEvent.__init__
です。スーパークラスメソッドは、非常に混乱するため、自動的には呼び出されません。
TypeTwoEvent.__init__
からEvent.__init__(self, ...)
を呼び出す必要があります(またはsuper
を使用しますが、慣れていない場合は、最初に読んで、何をしているのかを理解してください)。
継承されたクラスの__init__
メソッドから基本クラスの__init__
メソッドを呼び出す必要があります。
これを行う方法については here を参照してください。
私もこれに問題がありましたが、派生クラスの下部にsuper().__init__()
を置いたので、機能しません。初期化されていない属性を使用しようとするためです。