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

为何给TypeVar添加bound会导致mypy无法识别该Protocol?

带绑定TypeVar导致Protocol类型检查失败的原因分析

问题场景

以下代码中,func()内的x: Foo[V] = Bar[V]()赋值无法通过类型检查,但如果移除K的bound=int限制,赋值就能正常通过:

from typing import Generic, Protocol, TypeVar
T = TypeVar("T")
V = TypeVar("V")
K = TypeVar("K", bound=int)  # 带绑定的TypeVar

class Gen(Generic[T, K]):
    ...

class Foo(Protocol[T]):
    def g(self, t: Gen[T, K]) -> T:
        ...

class Bar(Generic[T]):
    def g(self, t: Gen[T, K]) -> T:
        raise RuntimeError

def func(v: V) -> None:
    x: Foo[V] = Bar[V]()  # 此处类型检查失败

核心原因

本质是Protocol的子类型检查规则和带绑定TypeVar的作用范围共同导致的:

  • 当K带bound=int时,Foo[T]这个Protocol对g方法的要求是:它必须能接受任意满足K <= int的Gen[T, K]实例(也就是所有int子类对应的Gen对象)。
  • 而Bar[T]的g方法虽然签名看起来一致,但Bar并没有把K作为自己的泛型参数。类型检查器会认为,Bar[T].g只能接受某个特定的K(符合int绑定的具体类型),而非所有符合约束的K。
  • Protocol要求实现类的方法参数类型必须满足逆变兼容:实现类的参数类型要能覆盖Protocol参数类型能接受的所有值。显然Bar[T].g做不到这一点,因此类型检查不通过。

当移除bound=int限制后,K变成无约束的TypeVar,此时Gen[T, K]可以匹配任何类型。Bar[T].g的参数类型和Foo[T].g的参数类型完全兼容,类型检查器会认为两者签名一致,因此赋值通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:10:29