You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:03:18