МУНИЦИПАЛЬНОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ДОПОЛНИТЕЛЬНОГО ОБРАЗОВАНИЯ
«ЦЕНТР ДЕТСКОГО ТЕХНИЧЕСКОГО ТВОРЧЕСТВА»
Методическая разработка
«Делегирование в Python»
к дополнительной общеобразовательной
общеразвивающей программе
технической направленности
«Программирование на Python»
Возраст детей: 10-17 лет
Автор: Костычев Вадим Александрович
г. Заречный Пензенской области
2026 г.
Данный материал предназначен для преподавателей информатики, программирования и студентов (учащихся), изучающих язык программирования Python. Он может быть использован как на лекциях, так и при проведении практических занятий или самостоятельной работе.
Цель: сформировать у учащихся понимание механизма делегирования как способа передачи части функциональности от дочернего класса родительскому, обеспечивая повторное использование кода и избегая дублирования.
Задачи:
Объяснить суть делегирования в контексте наследования.
Научить использовать функцию super() для вызова методов родительского класса.
Показать, как делегирование применяется при переопределении __init__ и других методов.
Разобрать порядок выполнения: когда сначала вызывать super(), а когда — свою логику.
Продемонстрировать практическую пользу делегирования на реалистичных примерах.
Что такое делегирование?
Делегирование — это передача части задачи другому объекту или компоненту. В повседневном программировании вы уже сталкивались с этим: когда вызываете функцию len() или print(), вы делегируете ей выполнение определённой работы.
В контексте ООП и наследования делегирование особенно важно, когда дочерний класс хочет использовать функциональность родителя, но при этом добавить своё поведение.
Пример без делегирования:
class Person:
def walk(self):
print("Человек идёт")
class Doctor(Person):
def walk(self):
print("Доктор идёт")
print("Человек идёт") # дублирование!
Здесь мы скопировали строку из родительского метода. Если завтра изменится логика Person.walk(), нам придётся править и Doctor.walk() — это неудобно.
Правильный подход — делегировать:
class Doctor(Person):
def walk(self):
super().walk() # вызываем родительский метод
print("Доктор идёт")
Теперь Doctor использует оригинальную реализацию, а не копирует её.
Как работает super()?
Функция super() возвращает временный объект родительского класса, через который можно вызвать его методы.
Синтаксис:
super().имя_метода(аргументы)
Важно:
- Не передавайте self вручную — он подставляется автоматически.
- super() всегда ссылается на ближайшего родителя в цепочке наследования.
Делегирование в __init__: избавление от дублирования
Рассмотрим типичную ситуацию:
class Person:
def __init__(self, name, surname):
self.name = name
self.surname = surname
class Doctor(Person):
def __init__(self, name, surname, age):
self.name = name # повтор!
self.surname = surname # повтор!
self.age = age
Это не только дублирование, но и нарушение принципа DRY (Don’t Repeat Yourself).
С помощью делегирования:
class Doctor(Person):
def __init__(self, name, surname, age):
super().__init__(name, surname) # передаём инициализацию родителю
self.age = age
Теперь:
- Родитель отвечает за свои атрибуты (name, surname).
- Дочерний — только за новые (age).
- Изменение в Person.__init__ автоматически повлияет на Doctor.
В каком порядке выполнять делегирование?
Когда в методе есть и своя логика, и вызов super(), порядок важен.
Вариант 1: сначала своя логика, потом super()
def __init__(self, name, surname, age):
self.age = age
super().__init__(name, surname)
Вариант 2: сначала super(), потом своя логика
def __init__(self, name, surname, age):
super().__init__(name, surname)
self.age = age
Какой правильный? Обычно — второй. Потому что родительский метод может изменять атрибуты объекта. Если вы сначала задали self.age = 25, а родительский __init__ содержит self.age = None, ваше значение будет перезаписано.
Пример ошибки:
class Person:
def __init__(self, name):
self.name = name
self.age = None # перезапишет!
class Doctor(Person):
def __init__(self, name, age):
self.age = age # сначала задали
super().__init__(name) # потом родитель поставил None!
Результат: Doctor("Шелдон", 30).age → None.
Правильно:
def __init__(self, name, age):
super().__init__(name) # сначала родитель
self.age = age # потом — своё
Выполняйте делегирование до своей логики, если родительский метод может влиять на состояние объекта.
Когда логика идёт ДО делегирования?
Иногда наоборот нужно сначала подготовить данные, потом вызывать родителя.
Пример из веб-разработки (Django):
def save(self, *args, kwargs):
self.slug = slugify(self.title) # сначала обновляем поле
super().save(*args, kwargs) # потом сохраняем в БД
Здесь важно, чтобы slug был вычислен до сохранения. Поэтому логика — перед super().
Правило:
- Если родитель инициализирует или сбрасывает атрибуты – super() сначала.
- Если вы подготавливаете данные для родителя – своя логика сначала.
Проверьте себя
1. Зачем использовать super() вместо прямого вызова Parent.method(self)?
2. Почему в super().method() не нужно передавать self?
3. Что произойдёт, если в __init__ сначала задать атрибут, а потом вызвать super().__init__()?
4. Приведи пример, когда логика должна идти до вызова super().
5. Можно ли делегировать не только __init__, но и другие методы? Приведи пример.
Заключение
- Делегирование — это вызов метода родительского класса из дочернего с помощью super().
- Оно устраняет дублирование и делает код гибким и поддерживаемым.
- При переопределении __init__ почти всегда нужно делегировать инициализацию родителю.
- Порядок вызова важен: обычно super() — первым, но бывают исключения.
- Делегирование — ключ к чистой архитектуре и профессиональному стилю ООП.
Освоив делегирование, вы перестанете копировать код и начнёте строить умные, расширяемые и надёжные классы — как настоящий разработчик.