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

如何用Python泛型为同类型(int/str)参数函数添加合规类型注解?

解决泛型函数中同类型int/str参数的mypy类型检查问题

需求是实现一个仅接受同类型int或str参数的函数,返回同类型结果,同时通过mypy静态类型检查,避免运行时类型不匹配的情况。以下是针对你遇到的问题的解决方案及分析:

问题分析

  • combine1的缺陷:允许传入不同类型参数(如int+str),且需要嵌套match做冗余类型检查,无法在静态阶段拦截错误。
  • combine2的缺陷:mypy无法在match分支中自动推断T的具体类型——虽然泛型约束了a和b同属T,但mypy不会主动关联分支内a和b的类型,导致返回值和操作数类型报错。

可行解决方案

方案1:使用TypeGuard做类型窄化

将类型检查逻辑封装为TypeGuard函数,明确告诉mypy参数的类型关系:

from typing import TypeGuard, TypeVar

T = TypeVar("T", int, str)

def is_both_int(a: T, b: T) -> TypeGuard[int, int]:
    return isinstance(a, int) and isinstance(b, int)

def is_both_str(a: T, b: T) -> TypeGuard[str, str]:
    return isinstance(a, str) and isinstance(b, str)

def combine(a: T, b: T) -> T:
    if is_both_int(a, b):
        return a + b
    elif is_both_str(a, b):
        return a + b
    else:
        # 静态检查阶段不会触发,因为T只能是int/str且参数同类型
        raise TypeError("参数必须同为int或同为str")

方案2:用assert辅助类型推断

利用泛型约束的特性,通过assert给mypy明确的类型提示:

from typing import TypeVar

T = TypeVar("T", int, str)

def combine(a: T, b: T) -> T:
    if isinstance(a, int):
        assert isinstance(b, int)
        return a + b
    elif isinstance(a, str):
        assert isinstance(b, str)
        return a + b
    else:
        raise TypeError("参数必须同为int或同为str")

注:运行时assert不会触发错误,因为静态检查已拦截不同类型参数的传入。

方案3:用cast手动断言类型

适合不想添加额外函数的场景,通过cast告诉mypy参数的具体类型:

from typing import TypeVar, cast

T = TypeVar("T", int, str)

def combine(a: T, b: T) -> T:
    match a:
        case int():
            return cast(T, a + cast(int, b))
        case str():
            return cast(T, a + cast(str, b))
        case _:
            raise TypeError("参数必须同为int或同为str")

方案对比

  • TypeGuard方案:逻辑清晰,类型检查可复用,静态检查最严格,适合复杂场景。
  • assert方案:代码简洁,无需额外函数,适合简单场景。
  • cast方案:无需额外逻辑,但需手动保证断言安全性,适合快速实现。

内容的提问来源于stack exchange,提问作者Pierre-olivier Gendraud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:55:01