Multiple inheritance: The derived class gets attributes from one base class only?

安稳与你 提交于 2019-12-23 03:18:06

问题


I was trying to learn the concepts of multiple-inheritance in Python. Consider a class Derv derived from two classes, Base1 and Base2. Derv inherits members from the first base class only:

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__)

The result is { 'x' : 10 } and reversing the order of inheritance gives only { 'y' : 10 }.

Shouldn't the derived class inherit attributes from both the base classes?


回答1:


I don't fully understand why it's like this, but I can tell you how to fix it:

For some reason, Python only calls the __init__ method of one of it's parents. However, this fixes your problem:

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}

Update, adding print statements actually sheds some light on the situation. For example,

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}



回答2:


When a class inherits from multiple superclasses, and there are 2 or more conflicting methods, the one in the first listed class is called. Because both Base1 and Base2 define __init__, the version of __init__ in the first listed class is called, therefore not defining both of the attributes.




回答3:


This is explained better in Python docs.

For most purposes, in the simplest cases, you can think of the search for attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy. Thus, if an attribute is not found in DerivedClassName, it is searched for in Base1, then (recursively) in the base classes of Base1, and if it was not found there, it was searched for in Base2, and so on.

Then, as __init__ is first find in your left class, it won't look for others. As other users explained, super() should be used to let Python know how to look for other __init__ methods.




回答4:


You could create objects with class attributes like this:

class Base1:
    x=10

class Base2:
    y=10

Then your Derv class would indeed inherit both properties.

class Derv (Base1, Base2):
    pass

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

The __init__ method is called when you create an instance of an object (ie, d = Derv()). An object can only have one version of a given method, so your Derv class only inherits the first one.



来源:https://stackoverflow.com/questions/52959041/multiple-inheritance-the-derived-class-gets-attributes-from-one-base-class-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!