JavaRush /Курсы /Модуль 1: Python Core /Множественное наследование

Множественное наследование

Модуль 1: Python Core
9 уровень , 9 лекция
Открыта

10.1 Наследование от нескольких классов

Множественное наследование в Python позволяет классу наследовать атрибуты и методы от более чем одного родительского класса. Это даёт большую гибкость и позволяет повторно использовать код, но также может привести к сложным иерархиям и потенциальным конфликтам.

Возможность перечислить своему классу пять родителей значительно расширяет ваши возможности и делает написание кода очень удобным. Сделать это очень просто — нужно просто перечислить классы-родители через запятую:


class Base1:
    def method1(self):
        print("Method1 from Base1")
        
class Base2:
    def method2(self):
        print("Method2 from Base2")
        
class Derived(Base1, Base2):
    pass
        
obj = Derived()
obj.method1()
obj.method2()     
        

Всё работает так, как и планировалось — красота.

Однако у множественного наследования есть несколько сложных сторон, которые обязательно нужно учитывать при его использовании. Давайте рассмотрим, как это работает и как избегать проблем, связанных с множественным наследованием.

10.2 Вызов метода, который есть у нескольких базовых классов

Класс может наследовать атрибуты и методы от нескольких родительских классов, перечисленных в скобках после имени класса. И эти атрибуты и методы могут иметь одинаковые названия:


class Base1:
    def method(self):
        print("Method from Base1")
        
class Base2:
    def method(self):
        print("Method from Base2")
        
class Derived(Base1, Base2):
    pass
        

obj = Derived()
obj.method() # чей метод тут вызовется?
        

В этом примере Derived класс наследуется от Base1 и Base2. Когда вызывается method(), Python выберет метод первого указанного класса — Base1.

Но это не так очевидно, не так ли? И если кто-то изменит код базового класса, может пострадать вся логика приложения, и вы даже не узнаете, что что-то не так. Просто начнут вызываться немного не те методы :)

10.3 Использование super() с множественным наследованием

Ещё одна интересная особенность — это вызов super() для базового класса при множественном наследовании.

Пример:


class Base1:
    def method(self):
        print("Method from Base1")
        super().method()
        
class Base2:
    def method(self):
        print("Method from Base2")
        super().method()
        
class Derived(Base1, Base2):
    def method(self):
        print("Method from Derived")
        super().method()
         

obj = Derived()
obj.method()
        

Ну что? Какой будет вывод на экран?

Method from Derived
Method from Base1

Или

Method from Derived
Method from Base2 

У меня для вас сюрприз — вывод будет таким:

Method from Derived
Method from Base1
Method from Base2

Код super().method() вызовет метод method() у каждого базового класса! Это как раз и есть те самые нюансы, о которых я говорил при первом упоминании множественного наследования.

10.4 Ромбовидное (Diamond) наследование

И наконец, классическая проблема ромбовидного наследования. Её легче показать на примере, чем описывать:

В виде кода это может выглядеть, например, так:


class A:
    def method(self):
        print("Method from A")
        
class B(A):
    def method(self):
        print("Method from B")
        super().method()
        
class C(A):
    def method(self):
        print("Method from C")
        super().method()
        
class D(B, C):
    def method(self):
        print("Method from D")
        super().method()
         
         
        
obj = D()
obj.method()
        

Вывод будет таким:

Method from D
Method from B
Method from C
Method from A 

Чтобы хоть как-то ориентироваться в множественном наследовании, вам нужно хорошо знать, в каком порядке Python ищет поля и методы у родительских классов. Именно об этом вы узнаете в следующей лекции.

2
Задача
Модуль 1: Python Core, 9 уровень, 9 лекция
Недоступна
Базовые классы.
Базовые классы.
2
Задача
Модуль 1: Python Core, 9 уровень, 9 лекция
Недоступна
Супер-экшен.
Супер-экшен.
Комментарии (27)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Dmitriy Уровень 23
11 февраля 2026

if hasattr(super(), "describe"):
    super().describe()
либо делать заглушку для MRO в Base2, убрав super
Анатолий Уровень 49
3 февраля 2026
❤️
Anonymous #980144 Уровень 25
12 декабря 2025
"Код super().method() вызовет метод method() у каждого базового класса!" Это утверждение в общем виде неверно, т. к. super().method() вызывает method() только у следующего класса в MRO. Утверждение верно только для конкретного примера, потому что в методе каждого класса иерархии явно вызывается super().method(). И, как уже тут писали, в стр. 9 будет ошибка, потому что следующий по MRO - класс Object, у которого такого метода нет.
Maksym Уровень 22
2 ноября 2025
A где задачи на Ромбовидное (Diamond) наследование?
Mikhail Уровень 26
27 сентября 2025
Мда... Просто лучшая лекция и практика!
Sergey Уровень 1
27 августа 2025
Просто нет слов , это дно
Леонид Уровень 17
24 августа 2025
Это что-то с чем-то, хуже лекции еще не встречал. Что свое же решение не принимать......
Михаил Уровень 52
17 августа 2025
у меня только один вопрос ))) зачем в реальном коде наследовать классы с одинаковыми методами? если надо писать классы так что бы они дополняли а не конфликтовали ))
AlterAyrol Уровень 25
22 октября 2025
в реальном коде - да. А вот на собеседованиях очень любят какое-нибудь всратое наследование спросить😅
shinobi Уровень 20
10 августа 2025
У первой и второй задачи абсолютно идентичные решения, даже идентификаторы схожие, зато у второй задачи нормальное описание и требования, а у первой будто от балды писали и ленились (хотя могли бы скопировать, ведь задачи идентичные)
SWK Уровень 26
7 апреля 2025
Волшебным образом решения 1й и 2й задачи идентичны с точностью до идентификаторов. Креатифф так и прёт...