如何将生成器按指定大小分块?相关实现与内存疑问
用生成器替代列表实现分块迭代的问题与解决
原列表分块实现
基于列表的分块生成器代码如下:
list_values = [...] gen = ( list_values[pos : pos + bucket_size] for pos in range(0, len(list_values), bucket_size) )
问题:替换为生成器后的实现与疑问
若将list_values替换为生成器以降低内存占用,尝试用itertools.islice实现:
gen = ( islice(list_values, pos, pos + bucket_size) for pos in range(0, len(list_values), bucket_size) )
但存在两个问题:
- 生成器无法调用
len(list_values),该如何替代? - 此场景下使用
islice能否降低峰值内存占用?
问题1解答:替代len()的实现方式
生成器/迭代器是消耗型且无固定长度的,无法通过len()获取长度,因此不能用range控制分块次数。正确的做法是循环从迭代器中批量取元素,直到迭代器耗尽,可实现如下自定义生成器函数:
from itertools import islice def chunk_generator(iterable, bucket_size): # 确保输入是迭代器(即使传入列表也转为迭代器) iterable = iter(iterable) while True: # 每次从迭代器中取最多bucket_size个元素 chunk = list(islice(iterable, bucket_size)) if not chunk: # 无元素时终止循环 break yield chunk
原理说明
- 迭代器是一次性消耗的,每次调用
islice会自动推进原迭代器的位置,无需手动记录pos; - 循环直到
islice返回的chunk为空,说明原迭代器已耗尽。
问题2解答:islice对峰值内存的影响
能有效降低峰值内存占用,原因如下:
- 原列表分块方式:需要先将整个列表加载到内存,峰值内存等于整个列表的大小;
- 生成器+
islice方式:原迭代器按需生成元素,每次仅将当前分块的元素保留在内存中(若转成列表);若直接返回islice迭代器而非列表,内存占用会更低——因为不会一次性把分块内的所有元素加载到内存,而是遍历时分批获取。
内容的提问来源于stack exchange,提问作者An old man in the sea.
相关产品推荐
相关产品推荐

