Декораторы

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

Вот простой пример декоратора:

def my_decorator(func):
    def wrapper():
        print("Перед вызовом функции")
        func()
        print("После вызова функции")
    return wrapper

@my_decorator
def hello_world():
    print("Hello, World!")

hello_world()

Когда вы запускаете этот код, вывод будет следующим:

Перед вызовом функции
Hello, World!
После вызова функции

Давайте разберемся, как работают декораторы шаг за шагом.

  1. Определение декоратора: Функция my_decorator принимает другую функцию в качестве аргумента и возвращает новую функцию-обертку wrapper.
  2. Объявление декорируемой функции: Функция hello_world декорируется с помощью @my_decorator.
  3. Выполнение: При вызове hello_world() сначала выполняется код внутри wrapper, затем сама функция hello_world, после чего снова выполняется оставшаяся часть кода в wrapper.

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

Применение декораторов:

  1. Логгирование:
import logging

logging.basicConfig(level=logging.INFO)

def log_function(func):
    def wrapper(*args, **kwargs):
        logging.info(f'Вызываю функцию {func.__name__}')
        result = func(*args, **kwargs)
        logging.info(f'Результат выполнения функции: {result}')
        return result
    return wrapper

@log_function
def add(a, b):
    return a + b

add(2, 3)
  1. Проверка типов:
def type_check(func):
    def wrapper(*args, **kwargs):
        for arg, expected_type in zip(args, func.__annotations__.values()):
            if not isinstance(arg, expected_type):
                raise TypeError(f'Ожидается тип {expected_type}, получено {type(arg)}')
        return func(*args, **kwargs)
    return wrapper

@type_check
def multiply(x: int, y: float):
    return x * y

multiply(3, 2.5)
  1. Кэширование:
from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

fibonacci(30)

Далее я поясню некоторые моменты, которые ранее не встречались в данном курсе. 

func.__name__

Это специальный атрибут любой функции в Python, который хранит имя этой функции. Например:

def greet():
    pass

print(greet.__name__)  # Выведет: 'greet'

Он полезен, когда необходимо получить имя функции динамически, например, для логгирования или отладки.

func.__annotations__.values()

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

Пример:

def multiply(x: int, y: float) -> float:
    return x * y

print(multiply.__annotations__)
# Выведет: {'x': <class 'int'>, 'y': <class 'float'>, 'return': <class 'float'>}

Метод .values() возвращает итерируемый объект, содержащий только значения этого словаря, то есть указанные типы.

def multiply(x: int, y: float)

 Эта запись указывает аннотации типов для аргументов функции. Здесь x обозначен как целое число (int), а y — как вещественное число (float). Аннотации помогают документировать ожидаемые типы аргументов и могут использоваться инструментами статической проверки типов, такими как mypy.

Пример:

def multiply(x: int, y: float) -> float:
    return x * y

result = multiply(3, 2.5)
print(result)  # Выведет: 7.5

Здесь мы указали, что параметр x должен быть типа inty должен быть типа float , а функция возвращает значение типа float.

Аннотации типов не влияют на выполнение функции, но служат для улучшения читаемости кода и поддержки инструментов анализа типа. Аннотации типов в Python – это способ указать типы данных для переменных, параметров функций и возвращаемых значений. Они появились в версии Python 3.5 и были введены через PEP 484. Хотя Python является языком с динамической типизацией, аннотации типов позволяют разработчикам добавлять статическую проверку типов, улучшая читаемость кода и помогая находить ошибки на этапе разработки.

Источник: https://stepik.org/lesson/1583954/step/1?unit=1605310

Было ли это полезно?

0 / 0