Многоуровневое наследование Python, __init__
Что касается множественного родительского наследования, когда я вызываю 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
Ответы
Ответ 1
Если вы хотите использовать super
в child
для вызова parent.__init__
и parent2._init__
, то оба родителя __init__
также должны вызвать 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)
Подробнее о последовательности вызовов __init__
, вызванных использованием super
, см. "Метод суперпотока 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)
. Это вызывает a TypeError
, поскольку object.__init__()
не принимает параметров.
Чтобы обойти эту проблему, вы можете создать класс Base
, который принимает аргументы __init__
, но не передает их на object.__init__
. Если parent
и parent2
наследуются от Base
, вы избегаете TypeError
.
Ответ 2
Потому что parent
следующий в порядок разрешения метода (MRO), и он никогда не использует super()
для вызова parent2
.
Ответ 3
См. этот пример:
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
class mro
класс super
ParentA
равен ParentB
, поэтому вам нужно вызвать super().__init__()
в ParentA
для 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'>]
Подробнее о MRO