Сравнение подходов
| Аспект | Подход из источника | Современная практика |
|---|---|---|
| Замер времени | time.time() |
time.perf_counter() — точнее для коротких интервалов |
| Метаданные | Использует functools.wraps |
Добавлять @functools.wraps ко всем ручным декораторам |
| Аргументы | *args, **kwargs |
То же + аннотации типов на фабриках |
| Ретрай | except Exception as e + time.sleep(5) |
Guard clauses, настраиваемый delay, логирование попыток |
| Стиль | Базовый PEP 8 | PEP 8 + type hints + f-strings + ранний возврат |
Пример: retry в современном стиле
import time
import functools
def retry(attempts: int, delay: float = 1.0):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(1, attempts + 1):
try:
return func(*args, **kwargs)
except Exception as exc:
print(f"Attempt {attempt} failed: {exc}")
if attempt == attempts:
print("All attempts exhausted.")
return None
time.sleep(delay)
return None # unreachable, but makes return path explicit
return wrapper
return decorator
Когда ничего не устарело
Исходный материал не содержит устаревших конструкций: синтаксис @decorator, *args/**kwargs, functools.wraps и фабрики декораторов остаются актуальными. Современные проекты дополняют их type hints, более точными таймерами и явной обработкой ошибок.
Проверить по документации: рекомендации по замерам времени — в документации time.perf_counter.