Лямбда-функции и декораторы - мощные инструменты Python, которые можно эффективно комбинировать для улучшения функциональности программы, особенно в ситуациях, где требуется краткое и элегантное решение.
Основные способы комбинации:
import functools
def timer(func):
@functools.wraps(func) #сохраняет имя и докстринг исходной функции
def wrapper(*args, **kwargs):
import time
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Функция {func.__name__} выполнилась за {end_time - start_time:.4f} секунд")
return result
return wrapper
# Декорируем лямбда-функцию, которая просто складывает два числа
add = timer(lambda x, y: x + y)
result = add(5, 3) # Вывод: Функция <lambda> выполнилась за ... секунд
print(result) # Вывод: 8
В этом примере декоратор `timer` измеряет время выполнения лямбда-функции, которая складывает два числа. Обратите внимание на использование `@functools.wraps` для сохранения метаданных (имя, докстринг) декорируемой функции. Без него имя функции было бы "wrapper", что затруднило бы отладку.
def repeat(num_times):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
# Декоратор, который повторяет выполнение функции 3 раза
@repeat(num_times=3)
def greet(name):
print(f"Привет, {name}!")
greet("Alice") # Вывод: Привет, Alice! (3 раза)
# Можно создать декоратор с помощью лямбды внутри:
create_greeting = lambda greeting: repeat(num_times=2)(lambda name: print(f"{greeting}, {name}!"))
greet_good_morning = create_greeting("Good morning")
greet_good_morning("Bob") # Вывод: Good morning, Bob! (2 раза)
В первом примере декоратор `repeat` принимает число `num_times` в качестве аргумента и возвращает другой декоратор, который повторяет выполнение декорируемой функции указанное количество раз. Во втором примере, лямбда-функция используется для создания нового декоратора `create_greeting`, который фиксирует определенное приветствие. Затем, этот новый декоратор применяется к другой лямбда-функции, которая выводит приветствие с именем.
def conditional_decorator(condition, decorator):
"""Применяет декоратор только если условие истинно."""
def wrapper(func):
if condition():
return decorator(func)
else:
return func
return wrapper
is_debug_mode = True # Предположим, флаг отладки
def debug(func):
"""Декоратор для логирования аргументов и результата функции."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
args_repr = [repr(a) for a in args]
kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]
signature = ", ".join(args_repr + kwargs_repr)
print(f"Вызывается {func.__name__}({signature})")
result = func(*args, **kwargs)
print(f"{func.__name__} вернула {result!r}")
return result
return wrapper
# Применяем декоратор debug только если is_debug_mode == True
@conditional_decorator(lambda: is_debug_mode, debug)
def calculate_sum(x, y):
return x + y
result = calculate_sum(2, 3) # Если is_debug_mode == True, выведет отладочную информацию
print(result) # Вывод: 5
is_debug_mode = False # Отключаем отладку
result = calculate_sum(2, 3) # Не будет выводить отладочную информацию
print(result) # Вывод: 5
В этом примере, `conditional_decorator` применяет декоратор `debug` только если `is_debug_mode` истинно. Лямбда-функция `lambda: is_debug_mode` используется для вычисления условия.
Преимущества:
Важно помнить:
В заключение, лямбда-функции и декораторы - ценные инструменты, которые при правильном использовании могут значительно улучшить код на Python, делая его более кратким, гибким и читаемым. Однако, важно помнить о читаемости и отладке, чтобы избежать усложнения кода.