Обновить

Комментарии 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
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS