sty*_*ybl 5 python generics python-3.x mypy
我有一些命名元组:
JOIN = NamedTuple("JOIN", [])
EXIT = NamedTuple("EXIT", [])
Run Code Online (Sandbox Code Playgroud)
我还有处理每种类型元组的函数:
def handleJoin(t: JOIN) -> bool:
pass
def handleExit(t: EXIT) -> bool:
pass
Run Code Online (Sandbox Code Playgroud)
我想做的是创建一个字典,handleTuple这样我就可以这样称呼它:
t: Union[JOIN, EXIT] = #an instance of JOIN or EXIT
result: bool
result = handleTuple[type(t)](t)
Run Code Online (Sandbox Code Playgroud)
我不知道如何定义所述字典。我尝试定义一个泛型T:
T = TypeVar("T", JOIN, EXIT)
handleTuple: Dict[T, Callable[[T], bool]
Run Code Online (Sandbox Code Playgroud)
但是我收到一条错误消息“类型变量 T 未绑定”,我不明白。到目前为止我得到的最接近的是:
handleTuple: Dict[Type[Union[JOIN, EXIT]], bool]
handleTuple = {
JOIN: True
EXIT: False
}
Run Code Online (Sandbox Code Playgroud)
这可以很好地按照我想要的方式调用它,但是我无法弄清楚Callable定义中的部分,因此我可以包含我的函数。我怎样才能做到这一点
TypeVars 仅在别名、类和函数中有意义。可以Protocol为查找定义 a :
T = TypeVar("T", JOIN, EXIT, contravariant=True)
class Handler(Protocol):
def __getitem__(self, item: Type[T]) -> Callable[[T], bool]:
...
handleTuple = cast(Handler, {JOIN: handleJoin, EXIT: handleExit})
Run Code Online (Sandbox Code Playgroud)
特殊方法self.__getitem__(item)对应于self[item]. 因此,协议定义访问handleTuple[item]withitem: Type[T]的结果为 some Callable[[T], bool]。cast目前,类型检查器(例如 MyPy)需要 来了解这是dict该协议的有效实现。
由于代码有效地实现了单个调度,因此定义一个functools.singledispatch函数提供了开箱即用的行为:
@singledispatch
def handle(t) -> bool:
raise NotImplementedError
@handle.register
def handleJoin(t: JOIN) -> bool:
pass
@handle.register
def handleExit(t: EXIT) -> bool:
pass
t: Union[JOIN, EXIT]
result: bool
result = handle(t)
Run Code Online (Sandbox Code Playgroud)