Python多继承,__ init__

Ren*_*enl 27 python oop inheritance init super

关于多父继承,当我打电话给super.__init__,为什么不__init__调用parent2的函数?谢谢.

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()
Run Code Online (Sandbox Code Playgroud)

输出是

9
10
5
11
12
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 26

如果你想用superchild打电话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)
Run Code Online (Sandbox Code Playgroud)

有关使用引起的调用序列的更多详细信息,请参阅"Python超级方法和调用替代方法".__init__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()
Run Code Online (Sandbox Code Playgroud)

您可能想知道,"为什么要使用Base?".如果parent并且parent2直接从中继承object, super(parent2,self).__init__(x,y)则会调用object.__init__(x,y).这提出了一个TypeError因为object.__init__()没有参数.

要解决此问题,您可以创建一个Base接受参数__init__但不传递参数的类object.__init__.随着parentparent2继承Base,你避免TypeError.


Ign*_*ams 9

因为parent方法解析顺序(MRO)中是下一个,它永远不会用于super()调用parent2.


Ste*_*ing 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())
Run Code Online (Sandbox Code Playgroud)

这将输出:

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'>]
Run Code Online (Sandbox Code Playgroud)

Python的多重继承就像一个链条,在Childmro中,super阶级的ParentAParentB,所以你需要调用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'>]
Run Code Online (Sandbox Code Playgroud)

有关MRO的更多信息