Python中按指定长度拆分生成器为子生成器的更Pythonic实现方法
更Pythonic的生成器分块实现方案
嘿,这个需求很常见,你当前的代码已经能完成任务,但确实可以借助itertools模块让代码更简洁、更符合Python风格,甚至还能避免手动维护临时列表的麻烦。
方法1:用itertools.islice实现通用版本
如果你的Python版本低于3.12,可以用itertools.islice循环切割原生成器,完全基于迭代器惰性操作,不需要手动管理索引和临时列表:
import itertools def create_sub_generators(generator, length=10): while True: # 每次从原生成器中截取length个元素的迭代器 chunk = itertools.islice(generator, length) # 检查子迭代器是否为空,避免最后返回空生成器 try: first_element = next(chunk) except StopIteration: return # 把取出的第一个元素和剩余元素重新组合成生成器返回 yield itertools.chain([first_element], chunk)
测试你的示例代码:
a = (i for i in range(100)) for index, sub_gen in enumerate(create_sub_generators(a, 22)): print(f'generator num: {index} length: {len([i for i in sub_gen])}')
运行结果和原代码完全一致:
generator num: 0 length: 22
generator num: 1 length: 22
generator num: 2 length: 22
generator num: 3 length: 22
generator num: 4 length: 12
这种方式的优势是内存效率更高,处理超大生成器时不会像原代码那样暂存元素到列表,完全依赖迭代器的惰性求值。
方法2:用itertools.batched(Python 3.12+)
如果你使用的是Python 3.12及以上版本,官方新增的itertools.batched函数专门解决迭代器分块问题,代码会简洁到极致:
import itertools def create_sub_generators(generator, length=10): # batched直接按指定长度拆分迭代器,返回每个块的元组迭代器 for chunk in itertools.batched(generator, length): yield iter(chunk)
同样测试你的示例,输出结果完全相同。需要注意的是,itertools.batched返回的每个块是tuple,如果你的场景直接用元组就能满足需求,甚至可以去掉iter()直接返回chunk。
和原代码的对比
- 原代码需要手动维护
to_return列表和索引判断,逻辑相对繁琐,且会暂存length个元素到列表后再转生成器,内存占用略高。 - 基于
itertools的版本完全遵循Python的“优雅”原则,代码简洁易读,利用迭代器特性实现惰性求值,内存效率更优。
内容的提问来源于stack exchange,提问作者pax80
相关产品推荐
相关产品推荐

