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

比较bound为int|float的TypeVar值时为何触发mypy报错?

mypy对bound为int|float联合类型的TypeVar报比较运算不支持错误的根本原因

问题场景

对类型标注为TypeVar('T', bound=int|float)的变量使用内置二元比较运算时,会触发意料之外的mypy类型报错。

最小复现代码

import typing

T = typing.TypeVar('T', bound=typing.Union[int, float])

def less_than(x: T, y: T) -> bool:
    return x < y

触发的报错信息

test.py:6: error: Unsupported operand types for < ("int" and "T")

补充验证现象

  • 将类型定义替换为T = typing.Union[int, float]时,mypy不会抛出上述报错
  • 将类型定义替换为T = typing.TypeVar('T', int, float)(将int、float作为TypeVar的独立约束参数,而非bound的联合类型)时,mypy也不会抛出上述报错

报错根本原因

这个报错是mypy的类型推导规则、TypeVar的语义差异、比较运算符的校验逻辑三者共同作用的结果:

  • 首先明确三种写法的语义差异:
    • T = TypeVar('T', bound=Union[int, float]):表示T是Union[int, float]的任意子类型。由于int、float在Python类型系统中允许被继承,mypy会默认存在用户自定义int/float子类的可能性,T的实际类型范围比“仅int或float本身”更大。
    • T = Union[int, float]:表示参数类型只能是int或者float本身,不存在其他可能类型。
    • T = TypeVar('T', int, float):表示T只能被绑定为int、float两个具体类型之一,不存在其他自定义子类的可能。
  • 其次是mypy对<比较运算符的校验逻辑:Python的比较运算依赖类的__lt__等魔术方法实现,int.__lt__声明的合法参数类型为int,float.__lt__声明的合法参数类型为float。校验x < y的合法性时,mypy会先取x的静态类型,检查该类型的__lt__方法是否接受y的静态类型作为参数。
  • 回到报错场景:当T是带bound的泛型时,mypy推导x的类型时,无法确定x到底是int的子类型还是float的子类型:如果x是int类型,它的__lt__只接受int参数,但y的类型T可能是float的子类型,无法证明一定符合参数要求;反过来如果x是float类型,也存在y是int子类型不匹配的可能,因此直接抛出操作数不支持的错误。
  • 另外两种写法不报错的核心原因:
    • 直接使用Union[int, float]作为参数类型时,mypy会对联合类型做全分支校验:分别验证x是int时y为int/float的比较合法性、x是float时y为int/float的比较合法性,所有分支都合法,因此不报错。
    • 使用带两个类型约束参数的TypeVar时,mypy明确知道T只能是int或float本身,不存在其他未知子类,同样会遍历两个类型的组合做校验,所有比较组合都合法,因此不报错。

内容的提问来源于stack exchange,提问作者jfschaefer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:36:18