多重继承:派生类仅从一个基类获取属性?

时间:2018-10-23 23:20:59

标签: python multiple-inheritance

我试图学习Python中的多重继承的概念。考虑从两个类DervBase1派生的一个类Base2Derv仅继承第一个基类的成员:

class Base1:
    def __init__(self):
        self.x=10

class Base2:
    def __init__(self):
        self.y=10

class Derv (Base1, Base2):
    pass

d = Derv()
print (d.__dict__)

结果为{ 'x' : 10 },颠倒继承顺序仅得到{ 'y' : 10 }

派生类是否应该继承两个基类的属性?

4 个答案:

答案 0 :(得分:3)

我不完全理解为什么会这样,但是我可以告诉您如何解决它:

由于某种原因,Python仅调用其父级之一的__init__方法。但是,这可以解决您的问题:

class Base1:
     def __init__(self):
         super().__init__()
         print('b1')
         self.x=10

 class Base2:
     def __init__(self):
         super().__init__() # This line isn't needed. Still not sure why
         print('b2')
         self.y=10

 class Derv (Base1, Base2):

     def __init__(self):
         super().__init__()

 d = Derv()
 print (d.__dict__)


'b2'
'b1'
{'y': 10, 'x': 10}

更新,添加打印语句实际上可以说明情况。例如,

class Base1:
     def __init__(self):
         print('Before Base1 call to super()')
         super().__init__()
         print('b1')
         self.x=10

 class Base2:
     def __init__(self):
         print('Before Base2 call to super()')
         super().__init__() # No remaining super classes to call
         print('b2')
         self.y=10

 class Derv (Base1, Base2):

     def __init__(self):
         super().__init__()

 d = Derv()
 print (d.__dict__)

'Before Base1 call to super()' # Just before the call to super
'Before Base2 call to super()' # Just before call to super (but there are no more super classes)
'b2' # Calls the remaining super's __init__
'b1' # Finishes Base1 __init__
{'y': 10, 'x': 10}

答案 1 :(得分:2)

当一个类继承自多个超类,并且有2个或更多冲突的方法时,将调用第一个列出的类中的一个。因为Base1Base2都定义了__init__,所以将调用第一个列出的类中__init__的版本,因此不会同时定义这两个属性。

答案 2 :(得分:1)

这在Python docs中有更好的解释。

  

对于大多数用途,在最简单的情况下,您可以想到搜索   对于从父类继承为深度优先的属性,   从左到右,在同一个班级中没有两次搜索   在层次结构中重叠。因此,如果在中找不到属性   DerivedClassName,在Base1中搜索,然后(递归)在   Base1的基类,如果在那里找不到,那就是   在Base2中搜索,依此类推。

然后,__init__首先在您的左类中找到,因此不会寻找其他人。正如其他用户解释的那样,应该使用super()来让Python知道如何寻找其他__init__方法。

答案 3 :(得分:0)

您可以使用以下类属性创建对象:

class Base1:
    x=10

class Base2:
    y=10

那么您的Derv类确实将继承这两个属性。

class Derv (Base1, Base2):
    pass

d = Derv()
print(d.x, d.y)  # prints: 10, 10

创建对象的实例(即__init__)时,将调用d = Derv()方法。一个对象只能具有给定方法的一个版本,因此您的Derv类仅继承第一个。