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

如何为泛型Number类的__add__方法编写灵活的Python类型提示?

解决泛型Number类跨类型加法的类型提示问题

要让泛型Number类支持跨数值类型(如int+float、Decimal+int等)的加法,同时让类型提示系统正确识别可接受的参数类型和返回结果类型,可以采用以下几种方案:

方案1:使用@overload明确声明跨类型场景

通过@overload装饰器为不同的参数类型组合定义精确的类型提示,适合需要严格类型校验的场景:

from typing import TypeVar, Generic, overload
from decimal import Decimal
from fractions import Fraction

# 限定T为支持的数值类型
T = TypeVar('T', int, float, Decimal, Fraction)

class Number(Generic[T]):
    value: T

    # 同类型相加
    @overload
    def __add__(self, other: T) -> Number[T]: ...
    @overload
    def __add__(self, other: "Number[T]") -> Number[T]: ...

    # int与float跨类型相加
    @overload
    def __add__(self, other: float) -> Number[float]: ...
    @overload
    def __add__(self, other: "Number[float]") -> Number[float]: ...
    @overload
    def __add__(self, other: int) -> Number[float]: ...
    @overload
    def __add__(self, other: "Number[int]") -> Number[float]: ...

    # Decimal与其他数值类型相加(结果为Decimal)
    @overload
    def __add__(self, other: int) -> Number[Decimal]: ...
    @overload
    def __add__(self, other: float) -> Number[Decimal]: ...
    @overload
    def __add__(self, other: Fraction) -> Number[Decimal]: ...
    @overload
    def __add__(self, other: "Number[int] | Number[float] | Number[Fraction]") -> Number[Decimal]: ...

    # 实际实现逻辑
    def __add__(self, other):
        other_val = other.value if isinstance(other, Number) else other
        result_val = self.value + other_val
        return Number(value=result_val)

这种方式能让类型检查器(如mypy、pyright)精确推断每个加法场景的返回类型,但需要手动覆盖所有需要支持的跨类型组合。

方案2:结合Protocol与关联泛型类型变量

定义一个支持加法的协议,用协变/逆变类型变量关联输入和输出类型,让类型系统自动推断结果:

from typing import TypeVar, Protocol, Generic, Union
from decimal import Decimal
from fractions import Fraction

# 定义逆变的输入类型和协变的输出类型
T_contra = TypeVar('T_contra', contravariant=True)
T_co = TypeVar('T_co', covariant=True)

class SupportsAdd(Protocol[T_contra, T_co]):
    """支持加法操作的协议,输入T_contra类型,返回T_co类型"""
    def __add__(self, other: T_contra) -> T_co: ...

# 限定Number的泛型参数为支持的数值类型
T = TypeVar('T', int, float, Decimal, Fraction)
# 结果类型变量,由类型检查器自动推断
R = TypeVar('R', int, float, Decimal, Fraction)

class Number(Generic[T]):
    value: T

    def __add__(self, other: Union[T, "Number[T]", SupportsAdd[T, R]]) -> Number[R]:
        other_val = other.value if isinstance(other, Number) else other
        result_val = self.value + other_val
        return Number(value=result_val)

此方案通过协议描述加法的类型关系,类型检查器会根据T和other的类型自动推断结果类型R,无需手动列举所有组合,扩展性更强。

方案3:利用类型检查器的内置推断(简洁版)

如果不需要极致的精确性,可以直接利用类型检查器对Python内置数值类型加法的支持,简化类型标注:

from typing import TypeVar, Generic, Union, Any
from decimal import Decimal
from fractions import Fraction

T = TypeVar('T', int, float, Decimal, Fraction)

class Number(Generic[T]):
    value: T

    def __add__(self, other: Union[T, int, float, Decimal, Fraction, "Number[Any]"]) -> "Number":
        other_val = other.value if isinstance(other, Number) else other
        result_val = self.value + other_val
        return Number(value=result_val)

这里返回类型写Number(不带泛型参数),类型检查器会自动根据实际运算结果推断具体的泛型类型,比如Number[int] + 3.14会被识别为返回Number[float]。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:10:57