Skip to content

Декораторы в python

Иногда нужно модифицировать существующую функцию, не меняя при этом ее исходный код. Чаще всего добавляется выражение для отладки, чтобы посмотреть, какие аргументы были переданы.
Декоратор - это функция, которая принимает одну функцию в качестве аргумента и возвращает другую функцию.

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, а также доп. данные:

Python
>>> 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

Как альтернатива созданию декоратора вручную (👆) можно просто добавить конструкцию @имя_декоратора перед функцией, которую нужно декорировать:

Python
>>> @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

Несколько декораторов

У каждой функции может быть больше одного декоратора:

Python
>>> def square_it(func):  # декоратор
        def new_function(*args, **kwargs):
            result = func(*args, **kwargs)
            return result * result
        return new_function

Декоратор, который ближе всего к функции (над def), будет выполняться первым и так наверх. Пример с двумя декораторами (с изменением их порядка для демонстрации):

Python
>>> @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. "Функции" --> "Декоратор"

python