Комментарии 5
А подскажите, плиз, как не сломать типы у метода/функции при использовании декоратора? Допустим, декоратор не меняет сигнатуру.
Если имеются в виду аннотации типов, то с версии 3.10 как-то так:
from functools import wraps
from typing import Callable, ParamSpec, TypeVar
P = ParamSpec("P")
T = TypeVar("T")
def decorator(func: Callable[P, T]) -> Callable[P, T]:
@wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
return func(*args, **kwargs)
return wrapper
@decorator
def greet(name: str) -> str:
return f"Hello {name}!"Менять сигнатуру тоже можно с помощью Concatenate, но, насколько я понял, есть ограничения
1001 статья про декораторы на Python, ничего нового, опять про одно и то же, остановитесь уже.
а вот так надо писать про декораторы, не повторяя "тысячу предыдущих" https://habr.com/ru/articles/750312/
спасибо за разбор, я бы добавил в статью пример декоратора, который сам принимает аргументы
например
from functools import wraps
from typing import Callable, TypeVar, ParamSpec
from loguru import logger
P = ParamSpec("P")
R = TypeVar("R")
def decorator_with_args(param: int, *, enabled: bool = True) -> Callable[[Callable[P, R]], Callable[P, R]]:
"""Фабрика декоратора — принимает параметры и возвращает декоратор."""
def decorator(func: Callable[P, R]) -> Callable[P, R]:
@wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
logger.info(f"decorator param={param}, enabled={enabled}, func={func.__name__}")
if not enabled:
return func(*args, **kwargs)
# Пример доп. логики до вызова
result = func(*args, **kwargs)
# Пример доп. логики после вызова
logger.debug(f"{func.__name__} -> {result!r}")
return result
return wrapper
return decoratorЗарегистрируйтесь на Хабре, чтобы оставить комментарий
Декораторы Python: пошаговое руководство