複数の親の継承について、super
.__init__
を呼び出すと、なぜparent2の__init__
関数が呼び出されないのですか?ありがとう。
class parent(object):
var1=1
var2=2
def __init__(self,x=1,y=2):
self.var1=x
self.var2=y
class parent2(object):
var4=11
var5=12
def __init__(self,x=3,y=4):
self.var4=x
self.var5=y
def parprint(self):
print self.var4
print self.var5
class child(parent, parent2):
var3=5
def __init__(self,x,y):
super(child, self).__init__(x,y)
childobject = child(9,10)
print childobject.var1
print childobject.var2
print childobject.var3
childobject.parprint()
出力は
9
10
5
11
12
super
でchild
を使用して_parent.__init__
_および_parent2._init__
_を呼び出す場合、親___init__
_ sもsuper
を呼び出す必要があります。
_class parent(Base):
def __init__(self,x=1,y=2):
super(parent,self).__init__(x,y)
class parent2(Base):
def __init__(self,x=3,y=4):
super(parent2,self).__init__(x,y)
_
super
を使用したことによる___init__
_の呼び出しシーケンスの詳細については、 "Pythonスーパーメソッドと代替呼び出し" を参照してください。
_class Base(object):
def __init__(self,*args):
pass
class parent(Base):
var1=1
var2=2
def __init__(self,x=1,y=2):
super(parent,self).__init__(x,y)
self.var1=x
self.var2=y
class parent2(Base):
var4=11
var5=12
def __init__(self,x=3,y=4):
super(parent2,self).__init__(x,y)
self.var4=x
self.var5=y
def parprint(self):
print self.var4
print self.var5
class child(parent, parent2):
var3=5
def __init__(self,x,y):
super(child, self).__init__(x,y)
childobject = child(9,10)
print childobject.var1
print childobject.var2
print childobject.var3
childobject.parprint()
_
「なぜBase
を使うのか」と疑問に思われるかもしれません。 parent
および_parent2
_がobject
から直接継承した場合、super(parent2,self).__init__(x,y)
はobject.__init__(x,y)
を呼び出します。 object.__init__()
はパラメーターを取らないため、これによりTypeError
が発生します。
この問題を回避するには、___init__
_への引数を受け入れるが_object.__init__
_に渡さないクラスBase
を作成します。 parent
と_parent2
_をBase
から継承すると、TypeError
を回避できます。
parent
は メソッド解決順序(MRO) の次であり、super()
を使用してparent2
を呼び出すことはないためです。
この例を見てください:
_class Base(object):
def __init__(self, c):
print('Base called by {0}'.format(c))
super().__init__()
class ParentA(Base):
def __init__(self, c):
print('ParentA called by {0}'.format(c))
super().__init__('ParentA')
class ParentB(Base):
def __init__(self, c):
print('ParentB called by {0}'.format(c))
super().__init__('ParentB')
class Child(ParentA, ParentB):
def __init__(self, c):
print('Child called by {0}'.format(c))
super().__init__('Child')
Child('Construct')
print(Child.mro())
_
これは出力します:
_Child called by Construct
ParentA called by Child
ParentB called by ParentA
Base called by ParentB
[<class '__main__.Child'>, <class '__main__.ParentA'>, <class '__main__.ParentB'>, <class '__main__.Base'>, <class 'object'>]
_
Pythonの多重継承はチェーンのようなものです。Child
クラスmro
では、super
のParentA
クラスはParentB
なので、次の呼び出しが必要ですParentA
のsuper().__init__()
をParentB
に初期化します。
super().__init__('ParentA')
をBase.__init__(self, 'ParentA')
に変更すると、継承チェーンが壊れて出力されます。
_Child called by Construct
ParentA called by Child
Base called by ParentA
[<class '__main__.Child'>, <class '__main__.ParentA'>, <class '__main__.ParentB'>, <class '__main__.Base'>, <class 'object'>]
_