Декораторы в python
Иногда нужно модифицировать существующую функцию, не меняя при этом ее исходный код. Чаще всего добавляется выражение для отладки, чтобы посмотреть, какие аргументы были переданы.
Декоратор - это функция, которая принимает одну функцию в качестве аргумента и возвращает другую функцию.
>>> def document_it(func):
def new_function(*args, **kwargs):
print('Running function:', func.__name__)
print('Positional arguments:', args)
print('Keyword arguments:', kwargs)
result = func(*args, **kwargs)
print('Result:', result)
return result
return new_function
Функция document_it() определяет декоратор, который:
- выведет имя функции и значения переданных в нее аргументов
- запустит функцию с полученными аргументами
- выведет результат
- вернет модифицированную функцию, готовую для использования
Передав любую функцию (func
) в document_it(), вернется новая функция с доп. выражениями, которые добавил document_it(). Декоратор не обязательно должен запускать код функции func
, но функция document_it() вызовет часть func
, чтобы вернуть результат работы функции func
, а также доп. данные:
>>> def add_ints(a, b):
return a + b
>>> add_ints(3, 5)
8
>>> cooler_add_ints = document_it(add_ints)
>>> cooler_add_ints(3, 5)
Running function: add_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
8
Как альтернатива созданию декоратора вручную (👆) можно просто добавить конструкцию @имя_декоратора перед функцией
, которую нужно декорировать:
>>> @document_it
def add_ints(a, b):
return a + b
>>> add_ints(3, 5)
Running function add_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
8
Несколько декораторов
У каждой функции может быть больше одного декоратора:
>>> def square_it(func): # декоратор
def new_function(*args, **kwargs):
result = func(*args, **kwargs)
return result * result
return new_function
Декоратор, который ближе всего к функции (над def), будет выполняться первым и так наверх. Пример с двумя декораторами (с изменением их порядка для демонстрации):
>>> @square_it
@document_it
def add_ints(a, b):
return a + b
>>> add_ints(3, 5)
Running function: add_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
64
>>> @document_it
@square_it
def add_ints(a, b):
return a + b
>>> add_ints(3, 5)
Running function: new_function
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 64
64
Функции в python
Соус: Книга “Простой Python” → Глава 9. “Функции” → “Декоратор”