Основы Python: Объектно-ориентированное программирование (ООП)
Наследование Часть 2: super()
Lesson 4 of 7 • 10 XP
Keep your place in this quest
Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.
Когда класс наследуется от родительского класса, дочерний класс может иметь свои собственные переменные экземпляра и методы, но иногда ему всё же нужно использовать части кода родителя.
И здесь на помощь приходит функция super().
Она позволяет дочернему классу получить доступ к методам (и косвенно атрибутам) родительского класса — без необходимости жестко прописывать имя родителя.
Одно из самых частых применений super() — вызвать конструктор родителя (__init__) из дочернего класса, чтобы родитель мог настроить свои атрибуты до того, как ребёнок добавит свои.
Когда вы создаёте дочерний класс с собственным методом init, он переопределяет init родителя. Это означает, что при создании объекта дочернего класса будет вызван только init дочернего — конструктор родителя не вызывается автоматически. В итоге любая логика инициализации, значения по умолчанию или атрибуты, определённые в init родителя, будут пропущены, и эти атрибуты останутся неопределёнными в том объекте. Это может привести к неожиданным ошибкам, если родительский класс отвечал за важную инициализацию. Чтобы этого избежать, следует явно вызвать super().init() внутри конструктора дочернего класса — это гарантирует, что инициализация родителя выполнится до добавления или переопределения чего-либо в ребёнке.
Давайте теперь это рассмотрим!
Зачем использовать super().__init__()?
При создании подкласса вы можете добавить новые данные для хранения.
Однако нужно, чтобы атрибуты родителя тоже были правильно инициализированы. Вместо переписывания кода инициализации родителя, просто вызывайте его через super().__init__().
Пример: добавление нового атрибута в подкласс
Допустим, у нас есть класс Animal, который хранит name и age.
Мы хотим сделать подкласс Dog, который дополнительно хранит breed (породу собаки), но при этом хотим пользоваться конструктором Animal для установки name и age.
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
class Dog(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age) # вызов конструктора Animal
self.breed = breed # добавляем атрибут Dog
Как это работает пошагово
- При создании объекта
Dogвызывается метод__init__классаDog. - Внутри
Dog.__init__вызываетсяsuper().__init__(name, age), который обращается кAnimal.__init__. - Конструктор родителя (
Animal.__init__) устанавливаетself.nameиself.age. - Управление возвращается обратно в
Dog.__init__, который устанавливаетself.breed.
Таким образом:
- Атрибуты родителя инициализируются так, как задумано родителем.
- Дочерний класс может добавлять свои атрибуты, не дублируя код.
Использование класса
dog = Dog("Rex", 4, "Golden Retriever")
print(dog.name) # Rex
print(dog.age) # 4
print(dog.breed) # Golden Retriever
Почему super() лучше, чем прямой вызов родителя по имени
Вы можете вызвать Animal.__init__(self, name, age) напрямую, но использование super() более гибко:
- Автоматически поддерживает множественное наследование (если класс наследует от нескольких родителей).
- Упрощает сопровождение кода — если вы переименуете родительский класс, не придётся менять все вызовы.
- Ясно показывает, что вы намеренно вызываете метод родительского класса.
Совет: всегда вызывайте `super().__init__()` перед установкой собственных атрибутов дочернего класса, чтобы все атрибуты родителя были готовы к использованию.
Итоги
super() — это ваша связь с родительским классом.
Используйте его, когда хотите:
- Повторно использовать код инициализации родителя.
- Расширять функциональность родителя без дублирования.
- Сохранять код чистым, удобным для сопровождения и гибким к изменениям в иерархии классов.
В следующем уроке мы изучим приватные методы и переменные — способ защитить внутренние данные класса от доступа и изменения извне.