Как в Python обратиться к методам родительского класса из дочернего?

Ответ

Для вызова методов родительского класса в Python используется встроенная функция super().

Это основной и рекомендуемый способ, так как он обеспечивает гибкость и корректно работает со сложными иерархиями наследования, включая множественное наследование, следуя Method Resolution Order (MRO).

Зачем это нужно?

Чаще всего super() используется для расширения, а не полного переопределения функциональности родительского метода. Например, чтобы вызвать конструктор родителя и добавить к нему новую логику в дочернем классе.

Пример:

class Vehicle:
    def __init__(self, brand):
        print("Инициализация Vehicle")
        self.brand = brand

    def display_info(self):
        print(f"Бренд: {self.brand}")

class Car(Vehicle):
    def __init__(self, brand, model):
        # 1. Вызываем __init__ родительского класса (Vehicle)
        super().__init__(brand)
        print("Инициализация Car")
        self.model = model

    def display_info(self):
        # 2. Вызываем display_info родителя, чтобы не дублировать код
        super().display_info()
        # 3. Дополняем его новой информацией
        print(f"Модель: {self.model}")

# Создаем экземпляр дочернего класса
my_car = Car("Tesla", "Model S")
my_car.display_info()

Вывод:

Инициализация Vehicle
Инициализация Car
Бренд: Tesla
Модель: Model S

Ключевые преимущества super():

  • Поддержка MRO: Гарантирует правильный порядок вызова методов в цепочке наследования.
  • Гибкость: Не нужно жестко прописывать имя родительского класса (Vehicle.__init__(self, ...)), что упрощает рефакторинг.
  • Краткость: В Python 3 вызов super() не требует аргументов.

Ответ 18+ 🔞

А, ну это ж классика, про которую все забывают, пока не наступят на грабли! Смотри, есть такая встроенная штука — super(). Её основная задача — звать методы из родительского класса. И это, блядь, не просто прихоть, а единственный адекватный способ, который не развалится в хлам при сложном наследовании, потому что он уважает этот ваш MRO (порядок разрешения методов).

Ну и нахуя это вообще?

Чаще всего, когда ты пишешь свой метод в дочернем классе, ты не хочешь полностью выкидывать родительскую логику, а просто добавить к ней что-то своё. Вот тут super() и спасает. Особенно в конструкторе __init__.

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

class Vehicle:
    def __init__(self, brand):
        print("Инициализация Vehicle")
        self.brand = brand

    def display_info(self):
        print(f"Бренд: {self.brand}")

class Car(Vehicle):
    def __init__(self, brand, model):
        # 1. Сначала вызываем родительский __init__, чтобы brand установился
        super().__init__(brand)
        print("Инициализация Car")
        # 2. А потом уже делаем свои дела
        self.model = model

    def display_info(self):
        # 3. Чтобы не копипастить вывод про бренд, зовем метод родителя
        super().display_info()
        # 4. И только потом дополняем своей инфой
        print(f"Модель: {self.model}")

# Ну и создаём нашу тачку
my_car = Car("Tesla", "Model S")
my_car.display_info()

Что на экране будет:

Инициализация Vehicle
Инициализация Car
Бренд: Tesla
Модель: Model S

Почему super() — это овердохуища, а не ручной вызов ParentClass.method(self)?

  • MRO, ёпта! Он сам разберётся в хитросплетениях твоего наследования и вызовет методы в правильном порядке. Без него можно так намудрить, что голова кругом пойдёт.
  • Гибкость. Не нужно вручную писать имя родительского класса. Захотел поменять иерархию — и не придётся полкласса переписывать.
  • Краткость. В третьем питоне super() вообще без аргументов работает, красота! Раньше-то надо было и класс, и self указывать, пиздец неудобно.