如何为Python类型提升函数简洁精确标注返回类型?
实现类型提升的精确泛型类型标注
在Python类型系统中,虽无直接对应C++ SFINAE的特性,但可通过泛型TypeVar结合条件类型或类型检查器自动推断实现简洁的类型提升标注,同时保证返回类型精确。
方案1:简化版@overload + TypeVar约束
若觉得全量@overload过于冗长,可只针对核心分支重载,用泛型兜底:
from typing import TypeVar, overload Num = TypeVar('Num', int, float) @overload def mul(a: int, b: int) -> int: ... def mul(a: Num, b: Num) -> float: return a * b
仅需两个分支:一个处理双int输入(返回int),另一个覆盖所有其他数值组合(返回float),兼顾简洁性与类型精确性,类型检查器可准确推断返回类型。
方案2:条件类型(需mypy 0.910+支持)
借助mypy的条件类型特性,直接描述类型提升规则,无需显式写@overload:
from typing import TypeVar, TypeAlias from typing_extensions import TypeIs T = TypeVar('T', int, float) U = TypeVar('U', int, float) # 定义提升规则:仅当两参数均为int时返回int,否则返回float PromotedType: TypeAlias = int if (TypeIs[T, int] and TypeIs[U, int]) else float def mul(a: T, b: U) -> PromotedType: return a * b
这种写法接近你想要的promote_types(T1, T2)风格,通过条件类型直接映射输入与返回类型的关系。
方案3:自定义类型提升协议(复杂场景适用)
若实际场景涉及更复杂的类型体系,可通过Protocol定义可提升类型,结合泛型实现通用逻辑:
from typing import TypeVar, Protocol, runtime_checkable @runtime_checkable class Numeric(Protocol): def __mul__(self, other: 'Numeric') -> 'Numeric': ... T = TypeVar('T', bound=Numeric) U = TypeVar('U', bound=Numeric) def promote_types(t: type[T], u: type[U]) -> type: if t is int and u is int: return int return float def mul(a: T, b: U) -> promote_types(type(a), type(b)): return a * b
该方案扩展性强,可根据自定义类型体系灵活调整promote_types的逻辑,保持代码简洁性。
内容的提问来源于stack exchange,提问作者Darkdragon84
相关产品推荐
相关产品推荐

