def my_decorator(func):
def wrapper(*args, **kwargs):
print("До вызова функции.")
result = func(*args, **kwargs)
print("После вызова функции.")
return result
return wrapper
def func1():
print("Функция 1")
def func2():
print("Функция 2")
func1 = my_decorator(func1)
func2 = my_decorator(func2)
def my_decorator(func):
def wrapper(*args, **kwargs):
print("До вызова функции.")
result = func(*args, **kwargs)
print("После вызова функции.")
return result
return wrapper
def func1():
print("Функция 1")
def func2():
print("Функция 2")
functions = [func1, func2]
for i, func in enumerate(functions):
functions[i] = my_decorator(func)
def apply_decorator_to_functions(decorator):
def apply(functions):
for i, func in enumerate(functions):
functions[i] = decorator(func)
return functions
return apply
def my_decorator(func):
def wrapper(*args, **kwargs):
print("До вызова функции.")
result = func(*args, **kwargs)
print("После вызова функции.")
return result
return wrapper
def func1():
print("Функция 1")
def func2():
print("Функция 2")
apply_my_decorator = apply_decorator_to_functions(my_decorator)
funcs = apply_my_decorator([func1, func2])
# Теперь func1 и func2 задекорированы (но не перезаписаны в глобальной области видимости)
Есть несколько способов применить один и тот же декоратор к нескольким функциям в Python. Важно понимать, что "одновременно" в данном контексте обычно означает избежать повторения кода декоратора для каждой функции вручную. Вот несколько подходов:
1. Применение декоратора непосредственно к нескольким функциям подряд:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Выполняется код до функции.")
result = func(*args, **kwargs)
print("Выполняется код после функции.")
return result
return wrapper
@my_decorator
def function_one():
print("Функция первая")
@my_decorator
def function_two():
print("Функция вторая")
function_one()
function_two()
Это самый простой и очевидный способ. Мы просто ставим @my_decorator
над каждой функцией, которую хотим декорировать. Этот подход хорошо работает, если функций немного.
2. Использование цикла (при определенных обстоятельствах):
Этот метод применим, когда функции хранятся в списке или другой итерируемой структуре. Не всегда возможно или желательно так делать, но иногда это полезно:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Выполняется код до функции.")
result = func(*args, **kwargs)
print("Выполняется код после функции.")
return result
return wrapper
def function_one():
print("Функция первая")
def function_two():
print("Функция вторая")
functions = [function_one, function_two]
for i in range(len(functions)):
functions[i] = my_decorator(functions[i])
function_one()
function_two()
Обратите внимание, что в этом случае мы присваиваем результат декорирования обратно элементам списка. Это изменяет исходный список функций. Также крайне важно выполнять это *вне* определения самих функций. Изменение глобальной области видимости внутри определения может привести к неожиданным результатам.
3. Создание класса-декоратора:
Классы-декораторы позволяют создавать более сложные декораторы, которые могут сохранять состояние или иметь параметризацию. Хотя они не обязательно упрощают применение к нескольким функциям одновременно, они обеспечивают лучшую организацию кода, особенно для сложных сценариев. Синтаксис применения остается тем же: @MyClassDecorator
.
class MyDecorator:
def __init__(self, message):
self.message = message
def __call__(self, func):
def wrapper(*args, **kwargs):
print(f"Сообщение декоратора: {self.message}")
result = func(*args, **kwargs)
return result
return wrapper
@MyDecorator("Привет от декоратора!")
def my_function():
print("Функция выполняется.")
my_function()
4. (Продвинутый) Создание функции для группового декорирования:
Можно создать функцию, которая принимает декоратор и список функций и применяет декоратор ко всем функциям в списке:
def decorate_multiple(decorator, functions):
for func in functions:
globals()[func.__name__] = decorator(func) # Модифицирует глобальную область видимости
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Код до функции")
result = func(*args, **kwargs)
print("Код после функции")
return result
return wrapper
def function_one():
print("Функция первая")
def function_two():
print("Функция вторая")
functions_to_decorate = [function_one, function_two]
decorate_multiple(my_decorator, functions_to_decorate)
function_one()
function_two()
Внимание! Этот метод использует globals()
для изменения глобальной области видимости. Это может быть небезопасным и не рекомендуется в большинстве случаев, особенно в больших проектах, так как затрудняет отладку и понимание кода. Лучше избегать изменения глобальной области видимости таким образом.
5. (Продвинутый) Использование метаклассов:
Этот подход значительно более сложный и используется реже. Он предполагает создание метакласса, который автоматически применяет декоратор ко всем функциям, определенным в классе. Это может быть полезно, если у вас есть много методов в классе, которые нужно декорировать одинаково.
В заключение, самый простой и распространенный способ – просто применить декоратор непосредственно к каждой функции, используя синтаксис @decorator_name
. Более сложные подходы, такие как использование циклов или функций для группового декорирования, следует использовать с осторожностью и только тогда, когда это действительно необходимо, чтобы избежать усложнения кода и потенциальных проблем с областью видимости.