如何为含TypeVar联合类型的Python函数精准标注返回类型?
解决方案:利用
@overload实现精准类型推导 要解决这个问题,核心是让类型检查器区分两个同类型的绑定类型参数和绑定类型与str混合的场景,单一的联合类型标注无法做到这点,必须用@overload定义多组函数签名,引导mypy做精准推导。
简化场景的实现代码
首先定义自定义的Comparable协议(这里用int作为示例bound,实际替换为你的自定义协议即可),再通过重载覆盖所有合法参数组合:
from typing import TypeVar, overload, Protocol # 定义自定义Comparable协议(示例仅适配int,实际替换为你的业务协议) class Comparable(Protocol): def __lt__(self, other: "Comparable") -> bool: ... def __le__(self, other: "Comparable") -> bool: ... # 按需补充其他比较方法 T = TypeVar('T', bound=Comparable) # 重载1:两个参数都是绑定类型T @overload def g(x: T, y: T) -> tuple[T, T]: ... # 重载2:第一个是T,第二个是str @overload def g(x: T, y: str) -> tuple[T, str]: ... # 重载3:第一个是str,第二个是T @overload def g(x: str, y: T) -> tuple[str, T]: ... # 重载4:两个参数都是str @overload def g(x: str, y: str) -> tuple[str, str]: ... # 实际实现 def g(x: T | str, y: T | str) -> tuple[T | str, T | str]: return x, y
验证效果
g(1, 2)→ 推导为tuple[int, int]g('hi', 'world')→ 推导为tuple[str, str]g(1, 'world')→ 推导为tuple[int, str]g({}, 3)→ mypy直接报错(dict未实现Comparable协议,也不是str)
实际业务场景(Interval类)的适配
针对你的Interval类需求,同样用重载区分上下界的合法组合,同时标注属性类型以支持合法操作校验:
from typing import TypeVar, overload, Protocol # 定义自定义Comparable协议 class Comparable(Protocol): def __lt__(self, other: "Comparable") -> bool: ... # 补充其他比较方法 # 定义inf单例的类型 class _PInf: pass class _NInf: pass PInf = _PInf() NInf = _NInf() BoundType = TypeVar('BoundType', bound=Comparable) class Interval: # 重载1:两个边界都是Comparable类型 @overload def __init__(self, lower: BoundType, upper: BoundType) -> None: ... # 重载2:下界是Comparable,上界是正无穷 @overload def __init__(self, lower: BoundType, upper: _PInf) -> None: ... # 重载3:下界是负无穷,上界是Comparable @overload def __init__(self, lower: _NInf, upper: BoundType) -> None: ... # 重载4:两个边界都是无穷 @overload def __init__(self, lower: _NInf, upper: _PInf) -> None: ... # 实际实现 def __init__(self, lower: BoundType | _NInf | _PInf, upper: BoundType | _NInf | _PInf) -> None: self.lower = lower self.upper = upper # 验证效果 valid_interval = Interval(1, 2) valid_interval.lower + 1 # mypy无报错(lower是int,支持加法) invalid_interval = Interval(NInf, 2) invalid_interval.lower + 1 # mypy报错(_NInf类型不支持加法)
关键优势
- 严格校验边界类型兼容性:非法类型(如
dict)传入会直接触发mypy错误 - 精准推导属性类型:mypy能识别
lower是Comparable类型还是inf类型,从而判断操作是否合法
内容的提问来源于stack exchange,提问作者Guybrush
相关产品推荐
相关产品推荐

