Вот декоратор, который принимает вызов (fn: Callable[P, Any]) с той же подписью, что и функция, обернутая. Он работает и тип проверяет.import inspect
from typing import Any, Callable, ParamSpec, TypeVar, Union
P = ParamSpec("P")
T = TypeVar("T")
def deco1(fn: Callable[P, Any]) -> Callable[[Callable[P, T]], Callable[P, T]]:
def decorator(wrapped_fn: Callable[P, T]) -> Callable[P, T]:
def inner(*args: P.args, **kwargs: P.kwargs) -> T:
fn(*args, **kwargs)
return wrapped_fn(*args, **kwargs)
return inner
return decorator
def logger1(x: int, y: str) -> None:
print(f"logger1: x={x}, y={y}")
@deco1(logger1)
def wrapped1(x: int, y: str) -> None: ...
wrapped1(1, "test") # prints "logger1: x=1, y=test"
Вот декоратор, который принимает вызов (fn: Callable[[], Any]) без аргументов. Это также работает и типа проверяет.def deco2(fn: Callable[[], Any]) -> Callable[[Callable[P, T]], Callable[P, T]]:
def decorator(wrapped_fn: Callable[P, T]) -> Callable[P, T]:
def inner(*args: P.args, **kwargs: P.kwargs) -> T:
fn()
return wrapped_fn(*args, **kwargs)
return inner
return decorator
def logger2() -> None:
print(f"logger2")
@deco2(logger2)
def wrapped2(x: int, y: str) -> None: ...
wrapped2(1, "test") # prints "logger2"
Я бы хотел объединить deco1 и deco2 в одну функцию deco3 . Следующие работают во время выполнения, но я не могу заставить проверку типа пройти. Это возможно?def deco3(
fn: Callable[[], Any] | Callable[P, Any],
) -> Callable[[Callable[P, T]], Callable[P, T]]:
def decorator(wrapped_fn: Callable[P, T]) -> Callable[P, T]:
def inner(*args: P.args, **kwargs: P.kwargs) -> T:
if len(inspect.signature(fn).parameters):
fn(*args, **kwargs)
else:
fn() # pyright error: Arguments for ParamSpec "P@deco3" are missing (reportCallIssue)
return wrapped_fn(*args, **kwargs)
return inner
return decorator
@deco3(logger1)
def wrapped_with_logger1(x: int, y: str) -> None: ...
@deco3(logger2) # pyright error: Argument of type "(x: int, y: str) -> None" cannot be assigned to parameter of type "() -> T@deco3"
def wrapped_with_logger2(x: int, y: str) -> None: ...
wrapped_with_logger1(1, "test") # prints "logger1: x=1, y=test"
wrapped_with_logger2(1, "test") # prints "logger2" but pyright error: Expected 0 positional arguments (reportCallIssue)
Подробнее здесь: https://stackoverflow.com/questions/796 ... allable-an
Набрать приверженность с помощью параметра или args (`` callable [p, any] | Callable [[], any] `) ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Ввод Callable с *args и аргументами, содержащими только ключевые слова
Anonymous » » в форуме Python - 0 Ответы
- 20 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Технические различия и преимущества: def (*args) и def (args=None) в Python [закрыто]
Anonymous » » в форуме Python - 0 Ответы
- 25 Просмотры
-
Последнее сообщение Anonymous
-