Множественное наследование: производный класс получает атрибуты только из одного базового класса? - PullRequest
0 голосов
/ 24 октября 2018

Я пытался изучить концепции множественного наследования в Python.Рассмотрим класс Derv, полученный из двух классов, Base1 и Base2.Derv наследует членов только из первого базового класса:

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 голосов
/ 24 октября 2018

Вы можете создавать объекты с атрибутами класса следующим образом:

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 наследует только первую.

0 голосов
/ 24 октября 2018

Когда класс наследует от нескольких суперклассов, и существует 2 или более конфликтующих методов, вызывается метод из первого перечисленного класса.Поскольку Base1 и Base2 определяют __init__, вызывается версия __init__ в первом перечисленном классе, поэтому не определяются оба атрибута.

0 голосов
/ 24 октября 2018

Это объясняется лучше в Документах Python .

В большинстве случаев в простейших случаях вы можете рассматривать поиск атрибутов, унаследованных от родительского класса, как глубину.во-первых, слева направо, , не выполняющий поиск дважды в одном и том же классе, где имеется перекрытие в иерархии .Таким образом, если атрибут не найден в DerivedClassName, он ищется в Base1, затем (рекурсивно) в базовых классах Base1, и если он там не был найден, он ищется в Base2 и т. Д.

Затем, поскольку __init__ впервые найден в вашем левом классе, он не будет искать других.Как объяснили другие пользователи, super() следует использовать, чтобы Python знал, как искать другие __init__ методы.

0 голосов
/ 24 октября 2018

Я не совсем понимаю, почему это так, но я могу рассказать вам, как это исправить:

По какой-то причине 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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...