Python多继承,__ init__

时间:2011-12-31 12:36:27

标签: python oop inheritance init super

关于多父继承,当我调用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 个答案:

答案 0 :(得分:26)

如果您想使用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 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?”。如果parentparent2直接从object继承,那么 super(parent2,self).__init__(x,y)会致电object.__init__(x,y)。由于TypeError没有参数,因此提出了object.__init__()

要解决此问题,您可以创建一个类Base,该类接受__init__的参数,但不会将它们传递给object.__init__。在parent继承parent2Base后,您可以避开TypeError

答案 1 :(得分:9)

由于parent位于method resolution order (MRO)的下一个位置,因此它永远不会使用super()来调用parent2

答案 2 :(得分:5)

见这个例子:

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多重继承就像一个链,在Childmro中,super ParentA类是ParentB,所以你需要调用{{ 1}} super().__init__()到初始ParentA

如果您将ParentB更改为super().__init__('ParentA'),则会破坏继承链,输出:

Base.__init__(self, 'ParentA')

有关MRO

的更多信息