Декораторы в 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. Они обеспечивают простой и единообразный способ изменения поведения функций и методов без необходимости изменять исходный код этих функций и методов. Их возможности включают логирование, кэширование, изменение аргументов или результатов и многое другое.
Содержание: