如何为存储子类与对应处理函数的字典f添加正确类型注解?
解决字典类型提示不兼容的问题
情况1:子类固定(仅A、B)
如果你的子类范围确定只有A和B,用TypedDict是最直接的方案,能精准约束每个键对应的函数类型:
from typing import TypedDict, Callable, Type class Sup: pass class A(Sup): pass class B(Sup): pass def get_A_report(a: A) -> int: return 1 def get_B_report(b: B) -> int: return 2 # 定义TypedDict,明确每个类键对应的函数签名 class ReportMap(TypedDict): A: Callable[[A], int] B: Callable[[B], int] # 给字典f添加类型提示 f: ReportMap = {A: get_A_report, B: get_B_report}
情况2:需要支持任意Sup子类(通用场景)
如果后续可能新增Sup的子类,用带逆变约束的TypeVar结合Mapping实现通用类型兼容:
from typing import TypeVar, Mapping, Callable, Type class Sup: pass class A(Sup): pass class B(Sup): pass # 定义绑定到Sup的逆变TypeVar,解决类型协变/逆变不兼容问题 T = TypeVar('T', bound=Sup, contravariant=True) def get_A_report(a: A) -> int: return 1 def get_B_report(b: B) -> int: return 2 # 用Mapping而非Dict(Dict是不变类型,无法利用协变/逆变规则) f: Mapping[Type[T], Callable[[T], int]] = {A: get_A_report, B: get_B_report}
为什么之前的写法报错?
你之前用Dict[Type[Sup], Callable[[Sup], int]]时,get_A_report的签名是Callable[[A], int],它并不等同于Callable[[Sup], int]——因为get_A_report只能接受A实例,无法处理任意Sup子类(比如B实例),所以类型检查器会判定不兼容。而用逆变TypeVar+Mapping的方式,能让类型检查器识别出:每个键对应的函数仅需接受该键类的实例即可,符合逆变的类型规则。
内容的提问来源于stack exchange,提问作者Vince
相关产品推荐
相关产品推荐

