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

如何通过Typing与Mypy在泛型中严格区分基类与派生类

解决方案

要让Mypy检测到fun(x1=B(), x2=A())和fun(x1=A(), x2=B())这类混合类型传参的错误,你可以通过以下两种方式实现精确类型匹配:

方法一:利用类型断言+Mypy严格检查

这种方式不需要修改函数的参数结构,只需调整内部逻辑并开启Mypy的严格类型断言检查:

修改代码

from typing import TypeVar
import dataclasses


@dataclasses.dataclass
class A:
    pass


@dataclasses.dataclass
class B(A):
    pass


T = TypeVar("T", A, B)


def fun(
    x1: T,
    x2: T,
) -> int:
    # 断言两个参数的精确类型完全一致,Mypy会基于此分析类型兼容性
    assert type(x1) is type(x2), "must be same type!"
    
    # 改用isinstance做类型判断,更符合Python类型规范
    if isinstance(x1, B):
        return 10
    elif isinstance(x1, A):
        return 5
    else:
        raise TypeError("Type not handled")


fun(x1=A(), x2=A())  # 正常通过
fun(x1=B(), x2=B())  # 正常通过
fun(x1=B(), x2=A())  # Mypy会报错:Assertion always fails
fun(x1=A(), x2=B())  # Mypy会报错:Assertion always fails

运行Mypy时开启严格类型断言

执行Mypy时添加--strict-type-predicates参数(或直接用--strict模式,该模式包含此参数):

mypy --strict-type-predicates your_script.py

方法二:显式传入类型参数(无需额外Mypy选项)

如果不想依赖命令行参数,可以通过显式传入类类型参数来锁定精确类型,让Mypy直接检测不匹配的情况:

from typing import TypeVar, Type
import dataclasses


@dataclasses.dataclass
class A:
    pass


@dataclasses.dataclass
class B(A):
    pass


T = TypeVar("T", bound=A)


def fun(
    x1: T,
    x2: T,
    *,  # 强制关键字参数,避免位置传参混淆
    cls: Type[T],
) -> int:
    if type(x1) is not cls or type(x2) is not cls:
        raise TypeError("must be same type!")

    if cls is A:
        return 5
    elif cls is B:
        return 10
    else:
        raise TypeError("Type not handled")


fun(x1=A(), x2=A(), cls=A)  # 正常通过
fun(x1=B(), x2=B(), cls=B)  # 正常通过
fun(x1=B(), x2=A(), cls=A)  # Mypy报错:x1类型为B,不符合预期的A
fun(x1=A(), x2=B(), cls=B)  # Mypy报错:x2类型为A,不符合预期的B

这种方式通过cls参数明确指定函数要处理的精确类型,Mypy会直接校验x1、x2的类型是否与cls匹配,无需额外命令行配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:17:13