Рубрики
Без рубрики

Декораторы в Python [объяснили]

Давайте поговорим о нишевой теме сегодня – декораторы в Python. Это простой, но мощный инструмент, который предлагает имя, украшает функции.

Автор оригинала: Pankaj Kumar.

Декораторы в Python [объяснили]

Давайте поговорим о нишевой теме сегодня – Декораторы в Python Отказ Это простой, но мощный инструмент, который предлагает имя, украшает Функции Отказ

Предварительное необходимое знание

Есть несколько концепций, которые нам нужно знать, прежде чем продолжить декораторы в Python, а именно Функции высшего порядка и Вложенные функции – Две стороны одной медали.

1. Функции более высокого порядка

Python имеет аккуратный способ проходить и возвращать функции и из других функций и из других функций. Это не поддерживается во многих языках программирования и позволяет программисту сделать ряд универсальных операций.

Именно здесь представлена концепция функций высшего порядка – любая функция, которая принимает или возвращает другую функцию, называется функцией более высокого порядка.

Например:

def hof(func, num):
    int res = func(num)
    return res

Как вы можете заметить, первый параметр HOF () это Func , что является функцией, которая называется позже. Аналогичным образом, функции более высокого порядка также возвращают другие функции.

Рекомендуется прочитать – Python рекурсивные функции

2. Вложенные функции

Еще одна универсальная функция, которую предлагает Python, это позволяет объявлять функции внутри функций, которые удобно называются вложенными функциями. Рассмотрим этот пример:

def func(num):
    def nested_func():
        return num
    return nested_func

Здесь Func () является функцией более высокого порядка, потому что она возвращает другую функцию, а nested_func () это вложенная функция (очевидно), потому что она определяется внутри другой функции.

Вы можете видеть, что определение вложенной функции полностью изменяется в зависимости от того, что вы отправляете на внешнюю функцию.

Это используется для реализации инкапсуляции и создания закрытий, что-то, что выходит из объема текущего учебника.

Что такое декораторы в Python?

Как мы обсуждали ранее, в Условиях Лэймана, декоратор украшает функции. Что это значит, это то, что декоратор оборачивает код или функциональность вокруг функции, чтобы улучшить то, что делает функция.

Давайте посмотрим на пример:

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

def sum(a, b):
    print(a + b)
Неопланированная функция - декораторы в Python

Теперь представьте, что вы собираетесь сделать тонну этих математических функций, которые принимают два числа и выполняют некоторые математические операции на них и распечатывают их результат (см. Python Print)

Теперь, давайте скажем, вы хотите добавить одну строку перед тем, как печатать результат, который рассказывает, что делается и какие числа работают на. Так что вывод выглядит что-то подобное:

## sum of 1 and 2 ##
3

Вы можете добавить эту строку при определении каждой функции, но если есть слишком много функций и Украшение Гораздо более одной строки, лучше использовать декоратор.

Синтаксис декоратора Python

def decorator(function):
    def wrapper(num1, num2):
        print("##", function.__name__, "of", num1, "and", num2, "##")
        function(num1, num2)
    return wrapper

Понимание этого куска кода может быть немного сложно, поэтому мы пройдем через эту строку по линии:

  • Def Decorator (Функция) : Есть несколько вещей, которые нужно отметить здесь. Во-первых, декоратор определяется как функция и ведет себя как функция. Лучше всего думать об этом как о функции. Во-вторых, и, что более важно, аргумент, который принимает декоратор, это функция, которую она украшает. Обратите внимание, что имя декоратора может быть чем угодно. Декоратор также может принимать несколько аргументов, но это тема для другой дискуссии.
  • Def Wrapper (NUM1, NUM2) : Это, вероятно, самая запутанная часть кода. Декоратор должен всегда возвращать функцию, которая добавила некоторую функцию в исходную функцию. Это обычно называется обертка функция. Эта новая функция заменит оригинальную функцию, поэтому она должна принять точно такое же количество аргументов Оригинальная функция имеет (в этом случае два). Так очевидно, этот декоратор не будет украсить функцию, которая не имеет ровно двух параметров, хотя есть способы обойти это, используя * args Отказ
  • Печать (...) : Это, в нашем случае, будет функциональность, который декоратор добавляет к исходной функции. Обратите внимание, что мы печатаем имя функции и два аргумента, точно так же, как мы хотели. После этого нам необходимо выполнить функцию, чтобы напечатана фактический выход.
  • Функция (NUM1, NUM2) : Ясно, как обертка () делает то же самое, что Функция () , но с дополнительной функциональностью, которая является то, что нам нужно, поэтому следующий шаг очевиден.
  • Обратная обертка : Так что в основном, декоратор () Сделал функцию от нас, завернул некоторые украшения вокруг него, используя обертка () , а потом вернулся обертка () который заменит первую функцию. Потому что обертка () Вызывает первую функцию и выполнять дополнительные вещи, это в основном расширенная версия первой функции.

Остальное из этого будет ясно, когда мы видим, как использовать декоратор.

Использование декораторов в Python

Теперь, когда мы определили декоратор по имени Декоратор Мы будем использовать его для улучшения трех функций – сумма (который мы видели ранее), Разница и Продукт Отказ

@decorator
def sum(a, b):
    print(a + b)

@decorator
def difference(a, b):
    print(a - b)

@decorator
def product(a, b):
    print(a * b)

Здесь символ @ Используется, чтобы сказать Python, что декоратор используется на следующей функции.

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

Давайте посмотрим на результат:

Декораторы в выходе Python

Обратите внимание, что звонить сумма () будет выполнять его улучшенную версию.

Примечание. Использование декоратора будет нарушать метаданные функции. В нашем примере звоня сумма .__ Имя__ вернется оболочка вместо сумма Потому что это функция, которую мы по существу используем. DOCSTRING также изменится в зависимости от того, что имеет DOCSTRING.

Чтобы избежать этого, просто импортировать Wraps от Functools а затем украсить обертку внутри декоратора, как:

from functools import wraps
def decorator(function):
    @wraps(function)
    def wrapper(num1, num2):
        print("##", function.__name__, "of", num1, "and", num2, "##")
        function(num1, num2)
    return wrapper

В этом сама обертка украшена с использованием метаданных функции, чтобы она сохраняет функцию Meta, как __name__ и его докстринг.

Заключение

Это было глубокое объяснение того, как использовать декоратор и что делает знак « @ ». Надеюсь, вы что-то узнали и увидимся в другом руководстве.

Использованная литература – https://www.python.org/dev/peps/pep-0318/