问题
Regarding multiple parent inheritance, when I call the super.__init__, why doesn't parent2's __init__ function get called? Thanks.
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()
Output is
9
10
5
11
12
回答1:
If you want to use super in child to call parent.__init__ and parent2._init__, then both parent __init__s must also call 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)
See "Python super method and calling alternatives" for more details on the sequence of calls to __init__ caused by using super.
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()
You might be wondering, "Why use Base?". If parent and parent2 had inherited directly from object, then
super(parent2,self).__init__(x,y) would call object.__init__(x,y). That raises a TypeError since object.__init__() takes no parameters.
To workaround this issue, you can make a class Base which accepts arguments to __init__ but does not pass them on to object.__init__. With parent and parent2 inheriting from Base, you avoid the TypeError.
回答2:
Because parent is next in method resolution order (MRO), and it never uses super() to call into parent2.
回答3:
See this example:
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())
This will output:
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 multiple inheritance is like a chain, in Child class mro, the super class of ParentA is ParentB, so you need call super().__init__() in ParentA to init ParentB.
If you change super().__init__('ParentA') to Base.__init__(self, 'ParentA'), this will break the inheritance chain, output:
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'>]
More info about MRO
来源:https://stackoverflow.com/questions/8688114/python-multi-inheritance-init