我已经成功地(这样 mypy 不会抱怨)为带有参数的装饰器编写了类型提示,这些参数装饰了 python 3.11.9 中的类方法:
import functools
from typing import Callable, TypeVar
MyClassType = TypeVar("MyClassType", bound=object)
T = TypeVar("T")
def reader(uri: str) -> Callable[[Callable[[MyClassType], T]], Callable[[MyClassType], T]]:
def decorator(fun: Callable[[MyClassType], T]) -> Callable[[MyClassType], T]:
@functools.wraps(fun)
def wrapper(subsys: MyClassType) -> T:
return fun(subsys)
wrapper.uri = uri
return wrapper
return decorator
def writer(uri: str) -> Callable[[Callable[[MyClassType, T], None]], Callable[[MyClassType, T], None]]:
def decorator(fun: Callable[[MyClassType, T], None]) -> Callable[[MyClassType, T], None]:
@functools.wraps(fun)
def wrapper(subsys: MyClassType, value: T) -> None:
fun(subsys, value)
wrapper.uri = uri
return wrapper
return decorator
class MyClass:
@reader("test")
def _my_reader(self) -> int:
return 1
@writer("test")
def _my_writer(self, val: float) -> None:
print(val)
现在我想缩短装饰器的返回类型提示,如下所示:
import functools
from typing import Callable, TypeVar, TypeAlias
MyClassType = TypeVar("MyClassType", bound=object)
T = TypeVar("T")
ReaderMethod: TypeAlias = Callable[[MyClassType], T]
WriterMethod: TypeAlias = Callable[[MyClassType, T], None]
# ReaderMethod = TypeVar("ReaderMethod", bound=Callable[[MyClassType], T])
# WriterMethod = TypeVar("WriterMethod", bound=Callable[[MyClassType, T], None])
def reader(uri: str) -> Callable[[ReaderMethod], ReaderMethod]:
def decorator(fun: ReaderMethod) -> ReaderMethod:
@functools.wraps(fun)
def wrapper(subsys: MyClassType) -> T:
return fun(subsys)
wrapper.uri = uri
return wrapper
return decorator
def writer(uri: str) -> Callable[[WriterMethod], WriterMethod]:
def decorator(fun: WriterMethod) -> WriterMethod:
@functools.wraps(fun)
def wrapper(subsys: MyClassType, value: T) -> None:
fun(subsys, value)
wrapper.uri = uri
return wrapper
return decorator
class MyClass:
@reader("test")
def _my_reader(self) -> int:
return 1
@writer("test")
def _my_writer(self, val: float) -> None:
print(val)
未注释或注释版本的 ReaderMethod/WriterMethod 都不起作用,mypy 抱怨第 18 行,例如“返回 TypeVar 的函数应该接收至少一个包含相同 TypeVar 的参数”,以及其他(类型提示)问题。我做错了什么?如何改进我的类型提示,以便我拥有这些别名 ReaderMethod/WriterMethod 并且 mypy 很高兴?
编辑:在第 15 行,mypy 抱怨“缺少泛型类型“ReaderMethod”的类型参数”,因此是问题的标题。
仅仅因为您定义了通用别名并不意味着您可以停止使用类型变量。
MyClassType
和 T
在 ReaderMethod
的使用中并不是“隐含”的,而是默默地传递到 wrapper
的定义。
您可能还需要一个别名来定义“变压器”类型。
type Transformer[F] = Callable[[F], F]
def reader(uri: str)[A, RV] -> Transformer[ReaderMethod[A, RV]]:
def decorator(fun: ReaderMethod[[A], RV]) -> ReaderMethod[[A], RV]:
@functools.wraps(fun)
def wrapper(subsys: A) -> RV:
return fun(subsys)
wrapper.uri = uri
return wrapper
return decorator