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
3 个回答
6
看看这个例子:
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
(方法解析顺序)中,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'>]
关于 MRO 的更多信息
10
因为parent
在方法解析顺序(MRO)中排在后面,而且它从来没有使用super()
去调用parent2
。
27
如果你想在child
类中使用super
来调用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)
想了解更多关于使用super
时__init__
调用顺序的细节,可以查看这个链接:"Python super method and calling alternatives"。
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)
。这会引发一个TypeError
错误,因为object.__init__()
不接受任何参数。
为了解决这个问题,你可以创建一个Base
类,它可以接受__init__
的参数,但不把这些参数传递给object.__init__
。这样,parent
和parent2
继承自Base
后,就可以避免TypeError
错误。