Python多重继承,初始化__

2024-06-26 13:23:03 发布

您现在位置:Python中文网/ 问答频道 /正文

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

Tags: selfchildobjectinitdefclassparentprint
3条回答

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

请参见以下示例:

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,因此需要调用super().__init__()中的ParentA来初始化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的详细信息

如果要使用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?”。如果parentparent2直接从object继承,那么 super(parent2,self).__init__(x,y)将调用object.__init__(x,y)。这会引发一个TypeError,因为object.__init__()不需要参数。

要解决此问题,可以创建一个类Base,该类接受__init__的参数,但不将它们传递给object.__init__。当从Base继承parentparent2时,可以避免TypeError

相关问题 更多 >