【问题标题】:Python multi-inheritance, __init__Python 多继承,__init__
【发布时间】:2025-12-04 10:40:02
【问题描述】:

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

【问题讨论】:

标签: python oop inheritance init super


【解决方案1】:

如果你想在child中使用super来调用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 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__。使用从 Base 继承的 parentparent2,您可以避免使用 TypeError

【讨论】:

    【解决方案2】:

    因为parentmethod resolution order (MRO) 中的下一个,它从不使用super() 调用parent2

    【讨论】:

    • 谢谢,但是对于父类,它的超类是对象吗?它将如何调用 parent2?
    • MRO 在涉及 MI 时并不关心当前的超类是什么。
    【解决方案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多重继承就像一个链,在Childmro中,ParentAsuper类是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的信息

    【讨论】:

    • 您应该指出您的示例适用于 Python 3。不带参数的 super() 在 Python 2 中将失败。