Декораторы — это мощный инструмент в Python, который позволяет изменять поведение функций или методов без изменения их исходного кода. Они предоставляют способ «оборачивания» одной функции другой функцией, что позволяет добавлять дополнительные функциональные возможности или логику перед выполнением основной функции.
Вот простой пример декоратора:
def my_decorator(func):
def wrapper():
print("Перед вызовом функции")
func()
print("После вызова функции")
return wrapper
@my_decorator
def hello_world():
print("Hello, World!")
hello_world()
Когда вы запускаете этот код, вывод будет следующим:
Перед вызовом функции
Hello, World!
После вызова функции
Давайте разберемся, как работают декораторы шаг за шагом.
- Определение декоратора: Функция
my_decoratorпринимает другую функцию в качестве аргумента и возвращает новую функцию-оберткуwrapper. - Объявление декорируемой функции: Функция
hello_worldдекорируется с помощью@my_decorator. - Выполнение: При вызове
hello_world()сначала выполняется код внутриwrapper, затем сама функцияhello_world, после чего снова выполняется оставшаяся часть кода вwrapper.
Декораторы особенно полезны для добавления повторяющейся функциональности, такой как логгирование, проверка доступа, кэширование и многое другое.
Применение декораторов:
- Логгирование:
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)
- Проверка типов:
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)
- Кэширование:
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 должен быть типа int, y должен быть типа float , а функция возвращает значение типа float.
Аннотации типов не влияют на выполнение функции, но служат для улучшения читаемости кода и поддержки инструментов анализа типа. Аннотации типов в Python – это способ указать типы данных для переменных, параметров функций и возвращаемых значений. Они появились в версии Python 3.5 и были введены через PEP 484. Хотя Python является языком с динамической типизацией, аннотации типов позволяют разработчикам добавлять статическую проверку типов, улучшая читаемость кода и помогая находить ошибки на этапе разработки.
Источник: https://stepik.org/lesson/1583954/step/1?unit=1605310
Было ли это полезно?
0 / 0