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

为何mypy中同一类型_CT被识别为非自身?

问题分析与解决

问题描述

以下代码试图实现工具函数lt_through,其返回的函数可作为类方法,让类的<运算符先将实例转换为指定的conv类型后再比较。但在严格模式下运行mypy时出现错误:

from typing import Callable, TypeVar, Type, Protocol

from typing_extensions import Self

_CT = TypeVar("_CT")
_T = TypeVar("_T")


class LtConverter(Protocol):
    def __new__(cls: Type[_T], x: _CT) -> _T: ...

    def __lt__(self, other: Self) -> bool: ...


def lt_through(conv: Type[LtConverter]) -> Callable[[_CT, _CT], bool]:
    def comparator(op: Callable[[LtConverter, LtConverter], bool]) -> Callable[[_CT, _CT], bool]:
        def method(self: _CT, other: _CT) -> bool:
            return op(conv(self), conv(other))  # conv(self)触发类型错误
        return method
    return comparator(lambda x, y: x < y)

报错信息:

main.py:18: error: Argument 1 to "LtConverter" has incompatible type "_CT"; expected "_CT"  [arg-type]

核心困惑:

  1. 为何_CT会被判定为与自身类型不兼容?
  2. 为什么conv(self)报错,而conv(other)无报错?

错误原因

  1. 类型变量未与协议绑定:顶层定义的_CT没有和LtConverter协议建立关联,mypy会将协议__new__方法中的_CT与函数lt_through里的_CT视为两个独立、无关联的类型变量,因此出现看似矛盾的“_CT与_CT不兼容”提示。
  2. self参数的类型检查特殊性:mypy对类方法中的self参数有特殊的类型校验逻辑,当类型绑定不清晰时,会优先触发self的类型不匹配报错,而other参数的问题暂时未被触发(本质上两者都存在类型绑定漏洞)。

解决方法

通过Generic让LtConverter协议与_CT类型变量关联,明确协议的转换源类型,同时统一类型变量的绑定关系:

from typing import Callable, TypeVar, Type, Protocol, Generic

from typing_extensions import Self

_CT = TypeVar("_CT")
_T = TypeVar("_T")


class LtConverter(Protocol[_CT]):  # 将_CT作为协议的泛型参数
    def __new__(cls: Type[_T], x: _CT) -> _T: ...

    def __lt__(self, other: Self) -> bool: ...


def lt_through(conv: Type[LtConverter[_CT]]) -> Callable[[_CT, _CT], bool]:
    def comparator(op: Callable[[LtConverter[_CT], LtConverter[_CT]], bool]) -> Callable[[_CT, _CT], bool]:
        def method(self: _CT, other: _CT) -> bool:
            return op(conv(self), conv(other))
        return method
    return comparator(lambda x, y: x < y)

关键修改点

  • 将LtConverter改为泛型协议LtConverter[_CT],明确协议依赖的转换源类型,让mypy能正确追踪类型变量的关联关系。
  • 在lt_through的参数和内部类型标注中,使用LtConverter[_CT]替代原始的LtConverter,确保类型变量的绑定完全一致。

修改后,mypy可正确推断所有类型,不会再出现类型不兼容的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:20:21