Для декоратора, сохраняющего сигнатуру, используйте ParamSpec для аргументов и TypeVar для результата. functools.wraps сохраняет метаданные, но не заменяет типовые аннотации.
Как правильно типизировать декоратор, чтобы mypy не ругался и подсказки IDE не ломались?
Для декоратора, сохраняющего сигнатуру, используйте ParamSpec для аргументов и TypeVar для результата. functools.wraps сохраняет метаданные, но не заменяет типовые аннотации.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Для декоратора, сохраняющего сигнатуру, используйте ParamSpec для аргументов и TypeVar для результата. functools.wraps сохраняет метаданные, но не заменяет типовые аннотации.
Пример для Python с доступным ParamSpec:
from functools import wraps
from typing import Callable, ParamSpec, TypeVar
P = ParamSpec('P')
R = TypeVar('R')
def logged(fn: Callable[P, R]) -> Callable[P, R]:
@wraps(fn)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
print(fn.__name__)
return fn(*args, **kwargs)
return wrapper
Так анализатор видит реальные параметры декорированной функции. Для изменения набора аргументов может понадобиться Concatenate, а для async-декоратора следует отдельно описать awaitable-результат. Callable[..., Any] скрывает ошибки вызова вместо решения типизации.
Источник: peps.python.org.