📜 Явный вызов родителя
В исходном материале этот способ показан как работающий, но нежелательный. Он вызывает метод конкретного класса напрямую.
class Employee:
def __init__(self, name):
self.name = name
class Programmer(Employee):
def __init__(self, name, language):
Employee.__init__(self, name) # явный вызов родителя
self.language = language
p = Programmer("Alice", "Python")
print(p.name, p.language)
❌ Почему этот подход плох
- Жёсткая привязка к имени родительского класса. Если родитель переименуется, придётся менять вызовы во всех наследниках.
- Не учитывает порядок разрешения методов (MRO). При изменении иерархии или множественном наследовании может вызваться не тот метод.
- Увеличивает риск забыть передать
selfвручную. - Без аннотаций типов сложнее понять, какие аргументы ожидаются.
✅ Современный вариант с super()
Функция super() сама находит ближайшего родителя согласно MRO. Код становится универсальным и безопасным при изменении иерархии.
class Employee:
def __init__(self, name: str) -> None:
self.name = name
class Programmer(Employee):
def __init__(self, name: str, language: str) -> None:
super().__init__(name)
self.language = language
p = Programmer("Alice", "Python")
print(p.name, p.language)
Что улучшилось:
- Нет жёсткой привязки к имени
Employee. - Корректно работает при многоуровневом наследовании.
- Аннотации типов делают интерфейс класса понятным.
- Меньше ошибок при рефакторинге.
🔗 Порядок разрешения методов
У каждого класса есть атрибут __mro__ (Method Resolution Order), который показывает порядок поиска методов. super() использует именно этот порядок.
class A:
pass
class B(A):
pass
class C(B):
pass
print(C.__mro__)
# (<class 'C'>, <class 'B'>, <class 'A'>, <class 'object'>)
Проверить по документации: подробнее о
super() и MRO см. Built-in Functions: super и method resolution order. Аннотации типов выходят за рамки исходного материала.