如何为生成对象分块的Python chunks函数添加正确类型提示?
正确为
chunks函数添加类型提示的方案 要解决这个函数的类型提示问题,我们需要利用Python的泛型TypeVar和可调用类型提示,来适配cls参数既可以是集合类型构造器(如list、tuple、dict)又可以是返回集合的函数(如sorted)的场景。
完整带类型提示的代码
from typing import Iterable, TypeVar, Callable, Iterator import itertools # 定义元素类型的泛型变量 Item = TypeVar('Item') # 定义集合类型的泛型变量,绑定到包含Item的可迭代类型 CollectionType = TypeVar('CollectionType', bound=Iterable[Item]) def chunks( iterable: Iterable[Item], chunk_size: int = 10, cls: Callable[[Iterable[Item]], CollectionType] = list ) -> Iterator[CollectionType]: _iter = iter(iterable) while True: values = cls(itertools.islice(_iter, chunk_size)) if not values: break yield values
关键部分解释
泛型变量定义
Item:用来追踪输入迭代器中元素的具体类型(比如int、str、tuple[K, V]等),让类型检查器能正确推断各场景下的元素类型。CollectionType:绑定到Iterable[Item],确保cls返回的集合是可迭代的(这样if not values的空值检查才合法),同时关联集合内的元素类型为Item。
cls参数的类型提示- 使用
Callable[[Iterable[Item]], CollectionType]:表示cls是一个可调用对象(可以是类构造器,比如list;也可以是普通函数,比如sorted),它接受一个包含Item类型元素的迭代器,返回CollectionType类型的集合。默认值list完全符合这个签名,因为list构造器本身就接受迭代器并返回列表。
- 使用
返回值类型提示
- 函数是生成器,所以返回
Iterator[CollectionType]:表示生成器会逐个产出CollectionType类型的集合,类型检查器会根据传入的cls自动推断具体的集合类型(比如list[int]、tuple[str]、dict[int, int]等)。
- 函数是生成器,所以返回
验证你的示例场景
我们可以确认这个类型提示能完美适配你给出的所有用法:
list(chunks(range(5), chunk_size=3)):类型推断为list[list[int]],正确。list(chunks((x for x in range(5)), chunk_size=3, cls=tuple)):类型推断为list[tuple[int]],正确。list(chunks('qwertyasdfgh', chunk_size=3, cls=sorted)):类型推断为list[list[str]],正确。list(chunks({x: x**2 for x in range(5)}.items(), chunk_size=3, cls=dict)):类型推断为list[dict[int, int]],正确。
注意事项(Python版本兼容)
如果你使用Python 3.9及以上版本,可以直接使用标准库的原生泛型(比如list[Item]、tuple[Item]),无需从typing模块导入Iterable,代码可以简化为:
from typing import TypeVar, Callable, Iterator import itertools Item = TypeVar('Item') CollectionType = TypeVar('CollectionType', bound=Iterable[Item]) def chunks( iterable: Iterable[Item], chunk_size: int = 10, cls: Callable[[Iterable[Item]], CollectionType] = list ) -> Iterator[CollectionType]: _iter = iter(iterable) while True: values = cls(itertools.islice(_iter, chunk_size)) if not values: break yield values
内容的提问来源于stack exchange,提问作者Alexander Myskin
相关产品推荐
相关产品推荐

