Самый простой вариант декоратора, который измеряет время выполнения функции:
import time
from functools import wraps
def timing_decorator(func):
# Используем wraps для сохранения метаданных функции
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.perf_counter() # Начальное время
result = func(*args, **kwargs) # Вызов оригинальной функции
end_time = time.perf_counter() # Конечное время
elapsed_time = end_time - start_time
print(f"Функция {func.__name__} выполнилась за {elapsed_time:.4f} секунд")
return result
return wrapper
@timing_decorator
def calculate_sum(n):
return sum(range(n))
result = calculate_sum(1_000_000)
Вывод:
Функция calculate_sum выполнилась за 0.0342 секунд
def timing_decorator(units='seconds'):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = func(*args, **kwargs)
end_time = time.perf_counter()
elapsed = end_time - start_time
if units == 'milliseconds':
elapsed *= 1000
unit_name = 'миллисекунд'
elif units == 'microseconds':
elapsed *= 1_000_000
unit_name = 'микросекунд'
else:
unit_name = 'секунд'
print(f"{func.__name__} - время выполнения: {elapsed:.2f} {unit_name}")
return result
return wrapper
return decorator
@timing_decorator(units='milliseconds')
def process_data(data_size):
return [x**2 for x in range(data_size)]
process_data(100_000)
Для случаев, когда нужно использовать время выполнения в коде:
def return_timing(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
return result, end - start
return wrapper
@return_timing
def complex_calculation(n):
return sum(x*x for x in range(n))
result, exec_time = complex_calculation(1_000_000)
print(f"Вычисления заняли {exec_time:.5f} секунд")
def method_timing_decorator(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
start = time.perf_counter()
result = func(self, *args, **kwargs)
elapsed = time.perf_counter() - start
# Используем имя класса и метода
print(f"{self.__class__.__name__}.{func.__name__} - {elapsed:.4f} сек")
return result
return wrapper
class DataProcessor:
@method_timing_decorator
def process(self, data):
time.sleep(0.5) # Имитация долгой обработки
return [x.upper() for x in data]
processor = DataProcessor()
processor.process(['a', 'b', 'c'])
import logging
from datetime import datetime
def logged_timing(logger=None):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start_time
log_msg = (
f"TIMING | {datetime.now().isoformat()} | "
f"{func.__module__}.{func.__name__} | "
f"{elapsed:.6f} сек"
)
if logger:
logger.info(log_msg)
else:
print(log_msg)
return result
return wrapper
return decorator
# Создаем логгер
logging.basicConfig(level=logging.INFO)
app_logger = logging.getLogger('app_performance')
@logged_timing(logger=app_logger)
def database_query():
time.sleep(0.1)
return "результат запроса"
database_query()
декораторы для измерения времени выполнения - это мощный инструмент для профилирования кода. Они позволяют легко добавлять временные метки к любым функциям без изменения их основного кода. Вы можете адаптировать приведенные примеры под свои нужды - добавлять логирование, сохранять результаты таймингов или настраивать формат вывода.