> Что такое декоратор в Python и для чего он используется? (Python)

Уровень: junior · Роль: backend · Язык: Python · Категория: Технические вопросы

Компании: Wildberries, JEDai, MirrorApp, Стилсофт, MTS, ООО Диджитал Сектор Поддержка, Aston, Ubic, Домклик, PositiveTechnologies, TrueEngineering, IPChain, JetLend, Фабрика решений, TradingView, ООО НТЦ Вулкан, praktika.ai, Сбер, Sunlight, mozen, ИВИ, Московский метрополитен

Стек: Python

> Пример ответа

Короткий ответ

Декоратор - это функция, которая принимает другую функцию (или класс) и возвращает новую функцию с расширенным поведением. Он позволяет добавлять логику до и после вызова исходной функции без изменения её кода. Используется для логирования, проверки прав, кеширования, измерения времени и других сквозных задач.

Подробное объяснение

Декораторы реализуют паттерн "обёртка" (wrapper). Синтаксически декоратор применяется через @decorator_name перед определением функции. Это эквивалентно записи func = decorator(func).

Ключевая идея - функция-декоратор возвращает новую функцию, которая обычно принимает *args и **kwargs, вызывает исходную функцию и дополняет её поведение. Декораторы могут быть параметризованы (через дополнительный уровень вложенности) и применяться к классам.

Важно понимать, что декоратор применяется один раз в момент определения функции, а не при каждом вызове. Это значит, что обёртка создаётся заранее, и все вызовы идут через неё.

На практике

Типичные сценарии: логирование вызовов, аутентификация в веб-фреймворках, мемоизация результатов, проверка типов аргументов, ретраи при ошибках. В Django и FastAPI декораторы используются для маршрутизации и валидации.

При написании декораторов важно сохранять метаданные исходной функции через functools.wraps, иначе потеряются __name__, __doc__ и другие атрибуты. Это критично для отладки и документации.

Пример кода

PYTHON
import functools
import time
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__} took {elapsed:.4f}s")
return result
return wrapper
@timer
def slow_add(a, b):
"""Складывает два числа."""
time.sleep(0.1)
return a + b
print(slow_add(2, 3)) # slow_add took 0.1001s
print(slow_add.__name__) # slow_add (благодаря wraps)

Как отвечать на собеседовании

Начни с простого определения, затем покажи понимание механики: декоратор - это функция высшего порядка. Обязательно упомяни functools.wraps и почему он нужен. Если спросят про параметризованные декораторы, покажи структуру с тройной вложенностью. Хорошо добавить пример из реального проекта, где декоратор решал конкретную задачу.

Что проверяет интервьюер

Интервьюер оценивает: понимание замыканий и функций высшего порядка, умение работать с *args/**kwargs, знание подводных камней (потеря метаданных, порядок применения нескольких декораторов). Также проверяется способность объяснить, когда декораторы уместны, а когда лучше использовать middleware или явные вызовы.

Типичные ошибки

  • Забыть functools.wraps - теряются метаданные.
  • Не возвращать результат исходной функции из wrapper.
  • Путать порядок применения нескольких декораторов (снизу вверх).
  • Пытаться использовать декоратор для задач, где нужен контекстный менеджер.
  • Не учитывать, что декоратор применяется один раз, а не при каждом вызове.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью