Развернутое объяснение
Базовая идея работы декоратора: «взять готовую функцию и добавить к ней расширенное поведение, не меняя её исходный код».
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 — внешняя обёртка.
На собеседовании можно сформулировать
Несколько декораторов на одной функции работают как вложенные обёртки. Они применяются снизу вверх, а выполняются как матрёшка: внешний декоратор вызывается первым, потом внутренний и сама функция, затем коды «после вызова» идут от внутреннего к внешнему.
На TeoBrain мы показываем это на примерах логирования, авторизации и измерения времени выполнения, чтобы вы видели живой эффект комбинации декораторов и могли уверенно объяснить порядок их работы на собеседовании.