Ошибка 1. Потеря результата
Проблема: результат оригинальной функции не возвращается.
def upper_decorator(func):
def wrapper(*args, **kwargs):
func(*args, **kwargs).upper() # результат не возвращается
return wrapper
@upper_decorator
def get_text():
return "hello"
print(get_text()) # None
Исправление:
def upper_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs).upper()
return wrapper
Ошибка 2. Потеря метаданных
Проблема: без functools.wraps декорированная функция называется wrapper.
def simple_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@simple_decorator
def example_function():
"""Original function."""
pass
print(example_function.__name__) # wrapper
print(example_function.__doc__) # None
Исправление:
import functools
def simple_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
Ошибка 3. Неправильный порядок декораторов
Проблема: ожидается один результат, а получается другой из-за порядка.
@border
@repeat
def f(): ... # repeat применяется первым
@repeat
@border
def g(): ... # border применяется первым
Исправление: помните, что декораторы выполняются снизу вверх, то есть ближайший к функции — первым.
Ошибка 4. Аргументы не передаются
Проблема: обёртка не принимает аргументы, поэтому декорированная функция не может быть вызвана с параметрами.
def bad_decorator(func):
def wrapper():
return func()
return wrapper
@bad_decorator
def add(a, b):
return a + b
add(2, 3) # TypeError
Исправление: используйте def wrapper(*args, **kwargs).
Ошибка 5. Декоратор с аргументами без фабрики
Проблема: пытаются использовать два уровня вместо трёх.
@framed("-") # TypeError: framed missing func
def show(): ...
Исправление: для параметризованных декораторов нужна фабрика:
def framed(symbol: str):
def decorator(func):
def wrapper(*args, **kwargs):
...
return wrapper
return decorator