@decorator — синтаксический сахар для вызова вида func = decorator(func). На одну функцию можно повесить несколько декораторов: применяются они снизу вверх, а выполняются как вложенные обёртки — от внешнего к внутреннему.
@decorator — синтаксический сахар для вызова вида func = decorator(func). На одну функцию можно повесить несколько декораторов: применяются они снизу вверх, а выполняются как вложенные обёртки — от внешнего к внутреннему.
Базовая идея декоратора: «взять готовую функцию и добавить к ней поведение, не меняя её исходный код».
def log_call(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
result = func(*args, **kwargs)
print(f"{func.__name__} finished")
return result
return wrapper
@log_call
def process_order(order_id):
print(f"Processing {order_id}")Строка @log_call эквивалентна записи:
process_order = log_call(process_order)То есть декоратор:
принимает исходную функцию func;
создаёт wrapper, который вызывает func и добавляет нужную логику до/после/вокруг вызова;
возвращает wrapper вместо оригинальной функции.
В backend‑коде через декораторы часто делают логирование, кеширование, авторизацию, ретраи и т.п.
Можно ли навешивать несколько декораторов?
Да, можно. Python позволяет «сложить» несколько декораторов над одной функцией:
@auth_required
@log_call
def get_user_profile(user_id):
...
# Эквивалентно:
def get_user_profile(user_id):
...
get_user_profile = auth_required(log_call(get_user_profile))Порядок такой: сначала log_call оборачивает исходную функцию, потом auth_required оборачивает результат log_call.
Порядок применения и выполнения
Важно различать две вещи:
Применение при определении: декораторы применяются снизу вверх (от ближайшего к функции к самому верхнему).
Выполнение при вызове: работают как матрёшка — сначала вызывается внешний декоратор (верхний в списке), затем внутренний, и в конце — сама функция.
def deco1(func):
def wrapper(*args, **kwargs):
print("deco1 before")
result = func(*args, **kwargs)
print("deco1 after")
return result
return wrapper
def deco2(func):
def wrapper(*args, **kwargs):
print("deco2 before")
result = func(*args, **kwargs)
print("deco2 after")
return result
return wrapper
@deco1
@deco2
def f():
print("func")
f()Вывод будет:
deco1 before
deco2 before
func
deco2 after
deco1 afterЗдесь deco2 ближе к функции, а deco1 — внешняя обёртка.
Фраза для собеседования
Декоратор — это функция, которая принимает другую функцию и возвращает обёртку с дополнительной логикой. Несколько декораторов работают как вложенные обёртки: применяются снизу вверх, а вызываются как матрёшка — сначала внешний декоратор, потом внутренний и в конце оригинальная функция.
Оцени свой прогресс