⚡ Краткий справочник
@decorator — применить декоратор к функции.
def wrapper(*args, **kwargs) — универсальная обёртка для любых аргументов.
@functools.wraps(func) — сохранить __name__ и __doc__.
@decorator(arg) — декоратор с аргументами (фабрика).
@outer
@inner — стекирование: применяется снизу вверх.
Синтаксис декораторов
| Запись | Что делает | Эквивалент |
@decorator | Применяет декоратор к функции | func = decorator(func) |
@decorator(arg) | Декоратор с параметром | func = decorator(arg)(func) |
@a @b def f() | Стекирование | f = a(b(f)) |
*args и **kwargs в декораторах
| Запись | Назначение | Пример вызова |
*args | Позиционные аргументы произвольной длины | func(1, 2, 3) |
**kwargs | Именованные аргументы произвольной длины | func(a=1, b=2) |
*args, **kwargs | Универсальная сигнатура обёртки | любой вызов |
| Запись | Что делает | Без неё |
@functools.wraps(func) | Копирует __name__, __doc__, __module__, __qualname__, __annotations__, __dict__ | wrapper скрывает оригинал |
Декоратор-фабрика
| Уровень | Назначение |
def retry(attempts): | Принимает аргументы декоратора |
def decorator(func): | Принимает декорируемую функцию |
def wrapper(*args, **kwargs): | Оборачивает вызов |
Порядок стекирования
| Запись | Порядок выполнения |
@border @repeat def f() | Сначала repeat, затем border |
@repeat @border def f() | Сначала border, затем repeat |
Правила использования
- Всегда используйте
def wrapper(*args, **kwargs), если декоратор должен быть универсальным.
- Всегда возвращайте результат
func(*args, **kwargs), если оригинал что-то возвращает.
- Всегда используйте
@functools.wraps(func), чтобы не терять метаданные.
- Для декораторов с аргументами добавьте ещё один уровень вложенности.
- Старайтесь не изменять сигнатуру декорированной функции без необходимости.