Python中能否为类型-处理函数字典添加合法类型标注以通过Mypy检查?
解决泛型调度字典的Mypy类型检查问题
假设我们有一个以抽象类Base为根的类继承体系,子类为A和B。想要通过一个字典实现类型到处理器函数的调度,原写法如下:
from typing import TypeVar, Callable, Type from abc import ABC class Base(ABC): pass class A(Base): pass class B(Base): pass RetType = int def a_handler(obj: A) -> RetType: return 1 def b_handler(obj: B) -> RetType: return 2 # *Mypy会报错:TypeVar "T" is unbound* T = TypeVar('T', bound=Base) dispatch: dict[Type[T], Callable[[T], RetType]] = { A: a_handler, B: b_handler }
但Mypy不支持这种顶层泛型字典的定义,会提示T无意义,且调用dispatch[type(x)](x)(其中x: Base)时无法通过类型检查。同时我们希望避免使用冗长的isinstance链式判断。
方案1:使用重载函数封装调度逻辑
通过@overload为调度函数定义具体类型的签名,让Mypy能准确推断类型:
from typing import overload @overload def handle(obj: A) -> RetType: ... @overload def handle(obj: B) -> RetType: ... def handle(obj: Base) -> RetType: # 字典可定义为普通的Base类型映射 dispatch: dict[Type[Base], Callable[[Base], RetType]] = { A: a_handler, B: b_handler } handler = dispatch[type(obj)] return handler(obj)
当调用handle(x)时,Mypy会根据x的具体类型(A或B)匹配对应的重载签名,确保类型安全,同时避免了链式判断。
方案2:使用类型断言简化字典定义
如果不想封装函数,可通过cast将处理器函数转换为统一的类型签名,让Mypy接受字典的定义:
from typing import cast dispatch: dict[Type[Base], Callable[[Base], RetType]] = { A: cast(Callable[[Base], RetType], a_handler), B: cast(Callable[[Base], RetType], b_handler) } # 调用时Mypy可通过类型检查 x: Base = A() result = dispatch[type(x)](x)
这种方式直接使用字典调度,仅通过少量类型断言让Mypy认可类型合法性。
内容的提问来源于stack exchange,提问作者ben w
相关产品推荐
相关产品推荐

