
本文讲解在 Python 中为分块(chunking)函数编写准确类型注解的方法,重点解决 TypeVar 约束中禁止使用泛型类型(如 Sequence[T])的限制,并提供符合 PEP 695 规范、兼容主流类型检查器(如 Pyright、mypy)的实用方案。
本文讲解在 python 中为分块(chunking)函数编写准确类型注解的方法,重点解决 `typevar` 约束中禁止使用泛型类型(如 `sequence[t]`)的限制,并提供符合 pep 695 规范、兼容主流类型检查器(如 pyright、mypy)的实用方案。
在 Python 类型系统中,为泛型分块函数(如将列表切分为子序列)添加精确类型提示时,一个常见误区是试图将 TypeVar 的约束(bound)设为另一个泛型类型,例如 T: Sequence[S]。但根据 PEP 695,类型变量的上界(bound)必须是具体(concrete)类型,不能是带参数的泛型类型——Sequence[T] 本身是泛型,因此 T: Sequence[T] 是非法的,Pyright 等检查器会报 reportGeneralTypeIssues 错误。
正确的做法是:避免在 TypeVar 定义中嵌套泛型约束,改为直接在函数签名中使用泛型类型参数。以下是推荐实现:
from typing import Generator, Sequence, TypeVar
T = TypeVar('T')
def chunk[T](sequence: Sequence[T], size: int) -> Generator[Sequence[T], None, None]:
for i in range(0, len(sequence), size):
yield sequence[i : i + size]
# 使用示例
foo: list[int] = [1, 2, 3, 4, 5]
bar = chunk(foo, 2)
# bar 的类型被推断为 Generator[Sequence[int], None, None]
# 若需 list[int],可显式转换或调整返回类型(见下文)
⚠️ 注意:上述实现返回 Generator[Sequence[T], ...],而非 list[T] —— 因为 sequence[i:i+size] 的切片结果类型取决于输入 sequence。例如传入 list[int] 时切片得 list[int],传入 tuple[str, ...] 时得 tuple[str, ...],故更精确的返回类型应为 Sequence[T](涵盖所有支持切片的序列类型)。
若你明确要求返回 list[T](例如强制转为列表),可稍作增强:
from typing import Generator, List, Sequence, TypeVar
T = TypeVar('T')
def chunk_as_list[T](sequence: Sequence[T], size: int) -> Generator[List[T], None, None]:
for i in range(0, len(sequence), size):
yield list(sequence[i : i + size]) # 显式转为 list[T]
# 此时 bar 的类型为 Generator[List[int], None, None]
foo: list[int] = [1, 2, 3, 4, 5]
bar = chunk_as_list(foo, 2) # ✅ 类型安全,bar 中每个元素均为 list[int]
✅ 总结:
- 不要尝试用
T: Sequence[S]这类嵌套泛型作为TypeVarbound; - 优先使用裸
TypeVar(如T = TypeVar('T')),并在参数/返回值中直接应用泛型类型(如Sequence[T]); - 切片操作的返回类型自动继承输入序列的类型构造器,若需统一为
list[T],请显式调用list(); - 该写法完全兼容 Python 3.12+ 的 PEP 695 新语法(如
def chunk[T](...)),也向后兼容 3.9+ 的typing模块。











