
Декораторы в Python — это мощный и гибкий инструмент, который позволяет изменять поведение функций или классов, не изменяя их исходный код. В этой статье мы подробно рассмотрим декораторы функций.
Декораторы — это, по сути, функции, которые «обертывают» другую функцию, модифицируя её поведение.
Это делает их идеальным инструментом для выполнения таких задач, как логирование, кэширование, проверка типов, измерение времени выполнения и многое другое.
def my_decorator(func):
def wrapper():
print("Before the function call")
func()
print("After the function call")
return wrapper
@my_decorator
def greet():
print("Hello, world!")
greet()
#Before the function call
#Hello, world!
#After the function callВ этом примере my_decorator — это декоратор. Когда мы вызываем greet(), на самом деле вызывается wrapper(), который в свою очередь вызывает greet().
Декораторы работают, используя два ключевых принципа Python:
Декоратор обычно определяется как функция, которая принимает один аргумент (функцию для декорирования) и возвращает новую функцию, которая заменяет оригинальную.
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapperЧтобы применить декоратор к функции, его имя указывается перед определением функции, предварительно снабдив его символом @.
@my_decorator
def greet():
print("Hello, world!")
greet()В текущем виде наш декоратор может работать только с функциями, которые не принимают аргументов. Чтобы сделать его более гибким, мы можем использовать *args и **kwargs в определении обертки, чтобы принимать любое количество позиционных и именованных аргументов.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
func(*args, **kwargs)
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
#Something is happening before the function is called.
#Hello, Alice!
#Something is happening after the function is called.В настоящее время наш декоратор не возвращает никакого значения из декорируемой функции. Чтобы исправить это, мы должны вернуть значение функции из нашего оберточного метода.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapperДекораторы могут использоваться для самых разнообразных задач. Вот несколько примеров.
1. Логирование
import logging
def log_decorator(func):
def wrapper(*args, **kwargs):
logging.info(f"Running {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_decorator
def some_function():
print("Running some_function")
some_function()2. Измерение времени выполнения
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = func(*args, **kwargs)
end_time = time.perf_counter()
print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds to run.")
return result
return wrapper
@timer_decorator
def slow_function():
time.sleep(2)
slow_function()3. Кэширование результатов
import functools
def cache_decorator(func):
cache = dict()
@functools.wraps(func)
def wrapper(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
@cache_decorator
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))Декораторы представляют собой мощный механизм для модификации поведения функций и методов в Python. Они обеспечивают простой и единообразный способ изменения поведения функций и методов без необходимости изменять исходный код этих функций и методов. Их возможности включают логирование, кэширование, изменение аргументов или результатов и многое другое.
Содержание: