Разбираюсь с декораторами в Python

Сегодня поговорю о декораторах в python. Все не очень опытные разработчики побаиваются декораторов, и я в их числе) Сами декораторы вроде как делают код прилежнее, но иногда в их внутренностях легко запутаться, особенно новичку. Начну с определения.

Определение

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

Пример простой

Допустим, у меня есть функция:

def summ():
    return 2 + 2

Ничего особенного. Складываю 2 и 2. Что, если я хочу изменить поведение функции, не меняя ее саму? Для этого и нужен декоратор. Хочу, чтобы результат умножался на 3. Для этого можно написать функцию, которая примет в качестве параметра мою функцию и умножит результат ее выполнения на 3. Ведь это питон, здесь все объекты и всех можно передавать в качестве аргументов.

def summ(): 
    return 2 + 2

def times3(f):
    return 3 * f()


new_summ = times3(summ)

В результате получаю 12

Теперь я перепишу этот код так, чтобы он выглядел по-питонячьи:

def times3(f):

    def inner_function():
        return 3 * f()

    return inner_function


@times3
def summ():
    return 2 + 2


if __name__ == "__main__":
    s = summ()

Результат предсказуемо тот же — 12

Следует помнить, что отныне функция  summ() всегда будет возвращать декорированный результат, т.е. 12.

Декоратор с параметрами

Это уже поинтереснее.

Теперь я хочу передавать числа, которые будут складываться, в качестве параметров функции  summ()

Сначала переписываю саму функцию, чтобы складывала передаваемые аргументы

def summ(a, b):
    return a + b

Обновляю декоратор

def times3(f):

    def inner_function(a, b):
        return 3 * f(a, b)

    return inner_function

Обратите внимание, внутренняя функция  inner_function() теперь принимает аргументы

И код полностью

def times3(f):

    def inner_function(a, b):
        return 3 * f(a, b)
    return inner_function

@times3
def summ(a, b):
    return a + b


if __name__ == "__main__":
    s = summ(2, 2)

Что будет на выходе? Неужели тоже 12?

Итоги

Итак, сегодня я написал короткую статью про декораторы в python, без которых нынче никуда. Когда-то и я не понимал их, но, надеюсь, чем-то помог. Примеры старался делать максимально простыми, чтобы не было каши перед глазами.

Дополнительно про декораторы в Python

Хочешь узнать еще больше о декораторах в python — читай pep 318 про декораторы, ведь их можно писать столбиком!

Ссылка на основную публикацию