如何在Python中正确注解可变参数泛型?
正确的类型注解方案
你可以利用Python 3.10+(或通过typing_extensions兼容3.8/3.9版本)的TypeVarTuple和Unpack特性来实现需求,无需编写多个重载就能支持任意数量的参数,且每个参数的泛型类型都能被正确推断。
完整代码示例
from typing import TypeVarTuple, Unpack, Tuple class A[T]: def __init__(self, value: T): self.value = value # 定义类型变量元组,用于表示任意数量的不同类型 Ts = TypeVarTuple('Ts') def func[*Ts](*args: Unpack[tuple[A[t] for t in Ts]]) -> Tuple[*Ts]: # 示例实现:提取每个A实例中的值并返回对应元组 return tuple(arg.value for arg in args)
关键说明
TypeVarTuple('Ts')定义了一个类型变量元组,它可以代表一组任意数量、任意类型的类型变量,正好匹配你需要的“每个T可以不同”的场景。*args: Unpack[tuple[A[t] for t in Ts]]表示:args是可变参数,其中每个元素的类型为A[t],t依次对应Ts中的每个类型变量。Unpack用于将生成的tuple类型展开为可变参数的类型约束。-> Tuple[*Ts]表示返回值是一个元组,元组中每个元素的类型与输入参数的泛型类型一一对应。
效果验证
当传入不同泛型类型的A实例时,类型检查器会自动推断返回值的具体类型:
a1 = A(1) a2 = A("hello") a3 = A(3.14) result = func(a1, a2, a3) # 类型检查器会推断result的类型为Tuple[int, str, float]
旧版本Python兼容方案
如果你的Python版本低于3.10且无法使用typing_extensions,可以保留重载方案,但优化通用注解的精度——不要直接用Any,而是用Tuple[Any, ...]明确返回是任意长度的元组,参数注解为*args: A[Any]:
from typing import overload, Tuple, Any class A[T]: pass @overload def func(arg: A[T]) -> T: ... @overload def func(arg1: A[T1], arg2: A[T2]) -> Tuple[T1, T2]: ... @overload def func(arg1: A[T1], arg2: A[T2], arg3: A[T3]) -> Tuple[T1, T2, T3]: ... # 可按需补充4、5个参数的重载 @overload def func(*args: A[Any]) -> Tuple[Any, ...]: ... def func(*args): # 实现逻辑 pass
内容的提问来源于stack exchange,提问作者Bharel
相关产品推荐
相关产品推荐

