如何为b.b获取tuple[A[int], A[int]]类型?TypeVarTuple展开问题
解决Python typing中TypeVarTuple的逐个泛型展开问题
问题重现
你当前的写法会导致类型被打包成A[*tuple[int, int]]而非逐个展开的tuple[A[int], A[int]],示例代码如下:
from typing import TypeVar, Generic, TypeVarTuple, Unpack, reveal_type T = TypeVar('T') class A(Generic[T]): pass Ts = TypeVarTuple('Ts') class B(Generic[Unpack[Ts]]): def __init__(self): self.b = (A[int](), A[int]()) b = B[int, int]() reveal_type(b.b) # 输出: tuple[A[*tuple[int, int]]]
对比C++的模板展开实现
C++中通过...运算符可以直接展开模板参数包,将每个Ts元素分别传入A:
#include <tuple> template <typename T> class A {}; template <typename... Ts> class B { public: std::tuple<A<Ts>...> b; B() : b(std::make_tuple(A<Ts>()...)) {} }; int main() { B<int, int> b; // b.b 类型为 std::tuple<A<int>, A<int>> return 0; }
Python中的解决方案
要在Python中实现等价效果,需要将TypeVarTuple的每个元素单独映射到A[T],再通过Unpack展开为元组类型。具体步骤如下:
- 定义类型别名,将
Ts中的每个元素T映射为A[T] - 在类的属性注解中使用
tuple[Unpack[<映射后的类型别名>]]明确类型
修正后的代码:
from typing import TypeVar, Generic, TypeVarTuple, Unpack, reveal_type T = TypeVar('T') class A(Generic[T]): pass Ts = TypeVarTuple('Ts') # 定义类型别名:将Ts的每个元素T转换为A[T] A_Tuple = tuple[A[T] for T in Ts] class B(Generic[Unpack[Ts]]): b: tuple[Unpack[A_Tuple]] # 展开映射后的类型为逐个A[T]的元组 def __init__(self): self.b = (A[int](), A[int]()) b = B[int, int]() reveal_type(b.b) # 输出: tuple[A[int], A[int]]
关键说明
- 直接使用
tuple[A[*Ts]]会将整个Ts元组作为单一参数传给A,这是导致类型不符合预期的核心原因 - 类型别名
tuple[A[T] for T in Ts]会遍历Ts的每个元素,为每个元素生成对应的A[T]类型 - 通过
Unpack将映射后的类型别名展开为元组的各个元素类型,实现和C++模板参数包展开等价的效果
内容的提问来源于stack exchange,提问作者Be3y4uu_K0T
相关产品推荐
相关产品推荐

