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

如何使用TypeVarTuple为批量创建类实例的函数添加正确的类型注解?

如何使用TypeVarTuple为批量创建类实例的函数添加正确的类型注解?

你想要的这种类型注解在Python 3.12+(或配合typing_extensions兼容更早版本)是完全可以实现的,你的思路方向是对的,只是参数的类型语法需要调整一下。

正确的类型注解实现

我们可以通过TypeVarTuple定义可变的类型元组,再利用Unpack拆解这个元组,分别对应“类的类型”和“实例的类型”:

from typing import TypeVarTuple, Unpack

# 定义可变类型元组Ts,代表要创建的实例的类型集合
Ts = TypeVarTuple("Ts")

def f[*Ts](
    *classes: Unpack[tuple[type[T] for T in Ts]]
) -> tuple[Unpack[Ts]]:
    return tuple(cls() for cls in classes)

这样写之后,mypy和Intellisense都能正确推断类型:

class A: pass
class B: pass
class C: pass

a, b, c = f(A, B, C)
reveal_type(a)  # 会显示类型为A
reveal_type(b)  # 会显示类型为B
reveal_type(c)  # 会显示类型为C

为什么你的初始写法不行?

你之前尝试的type[*Ts]语法不符合规则,因为Unpack(也就是泛型里的*用法)只能用在可变参数的位置,而type[]的括号里是单个类型的声明位置,不能直接拆解类型元组。我们需要先构造一个由type[T]组成的元组,再用Unpack把它拆解成可变参数的类型,这样就符合语法要求了。

备选方案:重载(你提到的思路)

如果你的项目需要兼容不支持PEP 646(泛型可变参数)的Python版本,那你之前想到的重载方案确实可行,虽然繁琐但能解决问题。你可以写多个@overload来覆盖不同参数数量的情况:

from typing import overload, TypeVar

T1 = TypeVar("T1")
T2 = TypeVar("T2")
T3 = TypeVar("T3")

@overload
def f[T1](cls1: type[T1]) -> tuple[T1]: ...

@overload
def f[T1, T2](cls1: type[T1], cls2: type[T2]) -> tuple[T1, T2]: ...

@overload
def f[T1, T2, T3](cls1: type[T1], cls2: type[T2], cls3: type[T3]) -> tuple[T1, T2, T3]: ...

# 可根据实际需求继续添加更多重载,覆盖到你需要的参数数量上限
def f(*classes):
    return tuple(cls() for cls in classes)

这种方式的缺点是需要手动维护多个重载,没法无限扩展参数数量,但如果你的实际场景中调用这个函数时传入的类数量不会太多,这也是一个稳妥的选择。

备注:内容来源于stack exchange,提问作者Dan Gittik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 15:34:31