> Что такое декоратор в Python и для чего он используется? (Python)
Уровень: junior · Роль: qa · Категория: Технические вопросы
Компании: Домклик, Сбер
Стек: Python
> Пример ответа
Короткий ответ
Декоратор в Python - это функция, которая принимает другую функцию (или класс) и возвращает новую функцию (или класс), расширяя её поведение без изменения исходного кода. Используется для добавления логирования, проверки прав, кэширования, замеров времени и других сквозных задач. Синтаксически применяется через @decorator перед определением функции. Это мощный инструмент метапрограммирования, основанный на замыканиях и функциях высшего порядка.
Подробное объяснение
Декоратор - это синтаксический сахар над обычным присваиванием: @decorator эквивалентно func = decorator(func). Функция-декоратор принимает целевую функцию как аргумент и возвращает обёртку (wrapper), которая обычно принимает *args, **kwargs, чтобы передать их исходной функции.
Основные варианты использования:
- логирование вызовов и аргументов
- контроль доступа (например, проверка роли пользователя)
- кэширование результатов (например,
@lru_cache) - измерение времени выполнения
- валидация входных данных
- ретраи (повторные попытки) при ошибках
Декораторы могут быть параметризованными (с аргументами) - тогда внешняя функция возвращает декоратор. Также существуют декораторы классов (например, @dataclass), которые модифицируют класс целиком.
Важно: декоратор применяется один раз при определении функции, а не при каждом вызове. Обёртка выполняется при каждом вызове, но сам декоратор - только в момент определения.
На практике
Для QA-инженера декораторы полезны при написании автотестов и вспомогательных утилит. Например, можно создать декоратор для повторного запуска flaky-тестов, для логирования шагов теста, для проверки предусловий или для сохранения скриншотов при падении.
Также декораторы часто встречаются в тестовых фреймворках (pytest, allure) - например, @pytest.mark.parametrize, @allure.step. Понимание их устройства помогает читать чужой код и отлаживать проблемы, связанные с обёртками (например, потеря имени функции без functools.wraps).
Пример кода
PYTHONimport functoolsimport timedef retry(max_attempts=3, delay=1):"""Декоратор для повторных попыток выполнения функции."""def decorator(func):@functools.wraps(func)def wrapper(*args, **kwargs):for attempt in range(max_attempts):try:return func(*args, **kwargs)except Exception as e:if attempt == max_attempts - 1:raiseprint(f"Attempt {attempt + 1} failed: {e}. Retrying...")time.sleep(delay)return wrapperreturn decorator@retry(max_attempts=2, delay=0.5)def unstable_request():# имитация нестабильного APIimport randomif random.random() < 0.5:raise ConnectionError("Network error")return "OK"print(unstable_request())
Как отвечать на собеседовании
Начни с простого определения: "декоратор - это функция, которая оборачивает другую функцию". Затем покажи синтаксис и объясни, что @decorator - это просто func = decorator(func). Приведи один-два реальных примера из своей практики (например, логирование или ретраи). Если спросят про параметризованные декораторы - объясни трёхуровневую вложенность. Упомяни functools.wraps для сохранения метаданных. Не углубляйся в сложные темы вроде декораторов классов, если не спрашивают.
Что проверяет интервьюер
Интервьюер проверяет:
- понимание принципа функций высшего порядка и замыканий
- знание синтаксиса
@и эквивалентного присваивания - умение объяснить, когда декораторы полезны, а когда вредны (избыточность)
- знание
functools.wrapsи проблем с метаданными - способность написать простой декоратор с нуля без подсказок
Для junior-уровня достаточно уверенного объяснения базового механизма и одного примера. Если кандидат путается в порядке аргументов параметризованного декоратора - это нормально, но базовую обёртку должен объяснить чётко.
Типичные ошибки
- Забывают
functools.wraps- теряется__name__и__doc__функции, что ломает интроспекцию и документацию. - Путают порядок вложенности для параметризованных декораторов: сначала аргументы декоратора, потом функция, потом
*args, **kwargs. - Считают, что декоратор выполняется при каждом вызове функции - на самом деле он выполняется один раз при определении.
- Не передают
*args, **kwargsв обёртке - функция с аргументами перестаёт работать. - Используют декораторы там, где достаточно обычного вызова функции - усложняют код без необходимости.
- Возвращают результат без
returnв обёртке - функция возвращаетNone.
> Похожие задачи по qa
Как оптимизировать SQL запросы
Используете ли Git
В чем разница реляционных и нереляционных баз данных
Что будет, если вызвать max вместо idxmax для поиска максимального значения?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью