Понимание декораторов Python с примерами

проекты Python Программирование и разработка

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

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

Концепция декораторов в Python помогает сохранить ваш код СУХИМ. Декоратор функций позволяет избежать ненужного повторения в кодовой базе, потому что некоторые повторяющиеся фрагменты кода можно объединить, чтобы они стали декораторами функций. По мере того, как вы продвигаетесь в использовании Python для разработки, декораторы могут помочь с аналитикой и ведением журнала. Они также необходимы для настройки валидации и проверок во время выполнения.

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

Что нужно понять, прежде чем углубляться в декораторы Python

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

Функция — это объект, а значит, ее можно присвоить другой переменной.

def greet():
    print("Hello John")
    
greet_john = greet
greet_john()
>>>
Hello John

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

Функция может быть возвращена из другой функции

def greet():
    def greeting_at_dawn():
        print("Good morning")
        
    return greeting_at_dawn

salute = greet()
salute()
>>>
Good morning

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

Функция может быть передана в качестве аргумента другой функции

def greet_some(func):
    print("Good morning", end=' ')
    func()

def say_name():
    print("John")

greet(say_name)
>>>
Good morning John

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

Читайте также:  Как в Python добавить в строку?

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

Как работают декораторы Python

Простая функция-декоратор начинается с определения функции, функции-декоратора, а затем вложенной функции во внешней функции-оболочке.

Всегда помните об этих двух основных моментах при определении декораторов:

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

Вот как выглядит основная функция декоратора в приведенном ниже фрагменте кода:

def increase_number(func):
    def increase_by_one():
        print("incrementing number by 1 ...")
        number_plus_one = func()  + 1
        return number_plus_one
    return increase_by_one 
    
def get_number():
    return 5
    
get_new_number = increase_number(get_number)
print(get_new_number())
>>>
incrementing number by 1 ...
6

Глядя на приведенный выше код, внешняя функция, increase_numberтакже известная как декоратор, получает аргумент функции func. increase_by_oneэто функция-оболочка, в которой находится украшенная get_numberфункция. Декоратор назначается другой переменной. Вот как выглядит синтаксис декоратора при использовании декораторов Python. Однако есть гораздо более простой способ представления декораторов.

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

def increase_number(func):
    def increase_by_one():
        print("incrementing number by 1 ...")
        number_plus_one = func()  + 1
        return number_plus_one
    return increase_by_one 
    
@increase_number    
def get_number():
    return 5

print(get_number())
>>>
incrementing number by 1 ...
6

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

Функции декоратора с параметрами

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

def multiply_numbers(func):
    def multiply_two_numbers(num1, num2):
        print("we're multiplying two number {} and {}".format(num1, num2))
        return func(num1, num2)
        
    return multiply_two_numbers

@multiply_numbers
def multiply_two_given_numbers(num1, num2):
    return f'{num1} * {num2} = {num1 * num2}'
    
print(multiply_two_given_numbers(3, 4))
 >>>
we're multiplying two number 3 and 4
3 * 4 = 12

Передача параметров внутренней функции или вложенной функции делает ее еще более мощной и надежной, поскольку дает больше гибкости для управления декорированной функцией. Любое количество аргументов ( *args) или аргументов ключевого слова ( **kwargs) может быть передано декорированной функции. *argsпозволяет собирать все позиционные аргументы, в то время **kwargsкак для всех аргументов ключевого слова, необходимых во время вызова функции. Давайте рассмотрим еще один простой пример:

def decorator_func(decorated_func):
    def wrapper_func(*args, **kwargs):
        print(f'there are {len(args)} positional arguments and {len(kwargs)} keyword arguments')
        return decorated_func(*args, **kwargs)
        
    return wrapper_func

@decorator_func
def names_and_age(age1, age2, name1='Ben', name2='Harry'):
    return f'{name1} is {age1} yrs old and {name2} is {age2} yrs old'
    
print(names_and_age(12, 15, name1="Lily", name2="Ola"))
>>>
There are 2 positional arguments and 2 keyword arguments
Lily is 12 yrs old and Ola is 15 yrs old

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

Читайте также:  Enum (перечисление) в Java

Несколько декораторов или цепочка декораторов в Python

Существует несколько вариантов использования декораторов функций в проекте Python. Другим вариантом использования может быть привязка декораторов (двух или более) к функции. Функция может быть украшена более чем одним декоратором (несколькими декораторами), и это достигается размещением одного декоратора поверх другого в произвольном порядке. У вас будет один и тот же вывод независимо от порядка, в котором несколько декораторов размещены друг над другом, как показано в следующем примере:

def increase_decorator(func):
    def increase_by_two():
        print('Increasing number by 2')
        new_number = func()
        return new_number + 2
        
    return increase_by_two
    

def decrease_decorator(func):
    def decrease_by_one():
        print('Decreasing number by 1')
        new_number = func()
        return new_number - 1
        
    return decrease_by_one
    
@increase_decorator
@decrease_decorator
def get_number():
    return 5
    
print(get_number())
>>> 
Increasing number by 2
Decreasing number by 1
6

Реальные примеры использования декораторов Python

Очень популярный способ использования декораторов в Python — регистратор времени. Это помогает программисту узнать, сколько времени требуется для выполнения функции, как способ измерения эффективности.

Мемоизация — еще один классный способ использования декораторов в Python. Результаты вызовов функций, которые повторяются без каких-либо изменений, можно легко запомнить при последующих вычислениях. Вы можете просто запомнить функцию с помощью декораторов.

Встроенные декораторы Python, такие как @classmethod(метод класса), @staticmethod(статический метод) и @propertyочень популярны в шаблоне декоратора ООП Python.

Заключение

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

Декораторы упрощают добавление дополнительных функций к простой функции, методу или классу без необходимости изменять исходный код, сохраняя при этом ваш код СУХИМ. Попробуйте декорировать функции самостоятельно, чтобы лучше понять шаблон декоратора.

Оцените статью
bestprogrammer.ru
Добавить комментарий

Adblock
detector