Декораторы — это мощный инструмент в Python, позволяющий модифицировать или расширять поведение функций и методов без изменения их исходного кода. В этой статье мы подробно рассмотрим, что такое декораторы, как они работают, и приведем примеры их использования.
Введение в декораторы
Что такое декоратор?
Декоратор — это функция, которая принимает другую функцию в качестве аргумента, выполняет некоторые операции и возвращает новую функцию или объект. Декораторы часто используются для добавления функциональности к существующим функциям, таких как логирование, проверка прав доступа или кэширование.
Основы синтаксиса
Синтаксис декораторов в Python включает символ @
, за которым следует имя декоратора, размещенное непосредственно перед объявлением функции:
@имя_декоратора
def функция():
# тело функции
Этот синтаксис эквивалентен следующему:
def функция():
# тело функции
функция = имя_декоратора(функция)
Пример создания простого декоратора
Рассмотрим простой пример создания декоратора, который выводит сообщение до и после выполнения функции:
def simple_decorator(func):
def wrapper():
print("До выполнения функции")
func()
print("После выполнения функции")
return wrapper
@simple_decorator
def say_hello():
print("Привет!")
say_hello()
В этом примере:
simple_decorator
— это декоратор, который принимает функциюfunc
в качестве аргумента.wrapper
— это внутренняя функция, которая выполняет дополнительные действия до и после вызоваfunc
.say_hello
— это декорируемая функция.
При вызове say_hello()
вывод будет следующим:
До выполнения функции
Привет!
После выполнения функции
Декораторы с аргументами
Декораторы также могут работать с функциями, принимающими аргументы. Для этого необходимо изменить внутреннюю функцию wrapper
так, чтобы она принимала произвольное количество аргументов и передавала их декорируемой функции:
def decorator_with_args(func):
def wrapper(*args, **kwargs):
print("До выполнения функции")
result = func(*args, **kwargs)
print("После выполнения функции")
return result
return wrapper
@decorator_with_args
def greet(name):
print(f"Привет, {name}!")
greet("Алексей")
В этом примере:
wrapper
принимает произвольное количество позиционных и именованных аргументов (*args
и**kwargs
).- Эти аргументы передаются декорируемой функции
greet
.
При вызове greet("Алексей")
вывод будет следующим:
До выполнения функции
Привет, Алексей!
После выполнения функции
Применение нескольких декораторов
Python позволяет применять несколько декораторов к одной функции. Декораторы применяются в порядке, начиная с ближайшего к функции:
def decorator_one(func):
def wrapper(*args, **kwargs):
print("Вход в декоратор один")
result = func(*args, **kwargs)
print("Выход из декоратора один")
return result
return wrapper
def decorator_two(func):
def wrapper(*args, **kwargs):
print("Вход в декоратор два")
result = func(*args, **kwargs)
print("Выход из декоратора два")
return result
return wrapper
@decorator_one
@decorator_two
def say_hello():
print("Привет!")
say_hello()
Вывод будет следующим:
Вход в декоратор один
Вход в декоратор два
Привет!
Выход из декоратора два
Выход из декоратора один
Полезные примеры использования декораторов
Логирование
Декораторы часто используются для логирования выполнения функций:
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Вызов функции {func.__name__} с аргументами {args} и {kwargs}")
result = func(*args, **kwargs)
print(f"Функция {func.__name__} вернула {result}")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
add(3, 5)
В этом примере:
- Декоратор
log_decorator
выводит информацию о вызове функцииadd
, ее аргументах и возвращаемом значении.
Проверка прав доступа
Декораторы могут использоваться для проверки прав доступа:
def require_auth(func):
def wrapper(*args, **kwargs):
user = kwargs.get('user')
if not user or not user.get('is_authenticated'):
print("Доступ запрещен")
return
return func(*args, **kwargs)
return wrapper
@require_auth
def view_dashboard(user):
print("Добро пожаловать на панель управления!")
view_dashboard(user={'is_authenticated': True})
view_dashboard(user={'is_authenticated': False})
В этом примере:
- Декоратор
require_auth
проверяет, аутентифицирован ли пользователь, и разрешает или запрещает доступ к функцииview_dashboard
.