← Назад к вопросам

Как работает super()?

2.0 Middle🔥 141 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает super()

super() — это встроенная функция в Python, которая позволяет обращаться к методам родительского класса. Это фундаментальный механизм наследования, и понимание его работает критично.

Базовый пример

class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return f"{self.name} издаёт звук"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # Вызываем __init__ родителя
        self.breed = breed
    
    def speak(self):
        parent_speak = super().speak()  # Вызываем speak родителя
        return f"{parent_speak}. Гав-гав!"

dog = Dog("Рекс", "Лабрадор")
print(dog.speak())  # Рекс издаёт звук. Гав-гав!

Как super() работает под капотом

super() возвращает объект-прокси, который ищет методы в MRO (Method Resolution Order) цепочки. MRO определяет порядок поиска методов при наследовании.

class A:
    def method(self):
        print("A")

class B(A):
    def method(self):
        print("B")
        super().method()

class C(A):
    def method(self):
        print("C")
        super().method()

class D(B, C):
    def method(self):
        print("D")
        super().method()

d = D()
d.method()
print(D.__mro__)

Вывод:

D
B
C
A
(<class D>, <class B>, <class C>, <class A>, <class object>)

MRO использует C3 линеаризацию Барретта, которая гарантирует порядок поиска при множественном наследовании.

super() с явными аргументами

В Python 2 требовалось явно передавать класс и self:

# Python 2
class Dog(Animal):
    def __init__(self, name):
        super(Dog, self).__init__(name)

В Python 3 это не нужно — super() использует неявно информацию из стека вызовов:

# Python 3
class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)  # Работает магически

Практические сценарии

1. Вызов инициализации родителя

class BaseRepository:
    def __init__(self, db_connection):
        self.db = db_connection

class UserRepository(BaseRepository):
    def __init__(self, db_connection, cache):
        super().__init__(db_connection)
        self.cache = cache

**2. Расширение методов с сохранением функциональности

class APIResponse:
    def to_dict(self):
        return {"status": "ok"}

class AuthenticatedResponse(APIResponse):
    def to_dict(self):
        base_dict = super().to_dict()
        base_dict["user_id"] = self.user_id
        return base_dict

3. Множественное наследование с миксинами

class TimestampMixin:
    def get_timestamp(self):
        from datetime import datetime
        return datetime.now()

class LoggerMixin:
    def log(self, message):
        print(f"[LOG] {message}")

class User(TimestampMixin, LoggerMixin):
    def __init__(self, name):
        self.name = name
        self.log(f"User {name} created at {self.get_timestamp()}")

user = User("John")  # [LOG] User John created at 2026-03-22 12:34:56.789123

Ошибки, которые я видел

❌ Забыть вызвать super() в init

class Dog(Animal):
    def __init__(self, name, breed):
        # Забыли super().__init__(name)
        self.breed = breed
        # self.name не инициализируется!

❌ Неправильный порядок наследования с миксинами

# ❌ Неправильно
class Model(TimestampMixin, DatabaseMixin):
    pass

# ✅ Правильно (миксины слева, базовые классы справа)
class Model(TimestampMixin, DatabaseMixin, BaseModel):
    pass

Когда НЕ использовать super()

Для прямого вызова конкретного класса без использования MRO:

# Если нужна 100% конкретная реализация
Animal.__init__(self, name)  # Явный вызов, не через MRO

Выводы: super() — мощный инструмент для правильного наследования. Понимание MRO критично для избежания ошибок при работе с наследованием, особенно при множественном наследовании.

Как работает super()? | PrepBro