You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python itertools.islice拆分生成器出现最后分片为空异常求解

问题根因
  • 普通迭代器是单向不可回溯、一次性消耗的对象,itertools.islice每次调用时,会从迭代器的当前已读取位置开始计数,而非从迭代器的初始起始位置计数。
  • 你原代码的非列表/元组分支完全复用了随机访问序列的下标逻辑,每次计算历史偏移量prev,调用islice(array, prev, next_),会导致每轮都会额外跳过prev个已经被读过的元素,直接提前耗空迭代器。

以你提供的测试用例拆解运行过程即可验证:

测试迭代器长度为8,拆分为3片,计算得到floor=2, rem=2,预期每轮分别取3、3、2个元素:

  1. 第一轮调用islice(iter, 0, 3):读取前3个元素[12,7,9],迭代器当前位置已经走到第4个元素(值为31)的位置
  2. 第二轮按原有逻辑计算得到prev=3,调用islice(iter, 3, 6):islice会先从当前位置(第4个元素)往后跳3个元素,跳过31、13、11,直接到第7个元素(值为7)的位置,再往后读最多3个,只能读到7、3两个,所以第二片输出[7,3]
  3. 第三轮计算得到prev=6,调用islice(iter,6,8):迭代器已经到末尾,跳6个直接超出范围,返回空列表

当分片数更多、每轮跳转的prev值更大时,会更早耗空迭代器,出现最后两个甚至更多分片为空的情况。

修复方案

非随机访问的迭代器分支不需要计算历史偏移量,每轮islice的起始位固定为0,仅控制每个分片要读取的长度即可,修复后代码如下:

import itertools


def divide_list(array, n, gen_length=None):
    """
    :param array: some iterable that you wish to divide
    :param n: the number of lists you would like to return
    :param gen_length: The length of the generator if array is a generator. Not necessary for lists and tuples.
    :return: a generator of the divided list

    Example:
    In: list(divide_list([1, 2, 3, 4, 5, 6, 7, 8, 9], 4))
    Out: [[1, 2, 3], [4, 5], [6, 7], [8, 9]]
    """
    if isinstance(array, (list, tuple)):
        floor, rem = divmod(len(array), n)
        items_index = (0, floor)
        for _ in range(n):
            prev, next_ = items_index[0], items_index[1] + 1 if rem > 0 else items_index[1]
            yield array[prev:next_]
            items_index = (next_, next_ + floor)
            rem -= 1
    else:
        floor, rem = divmod(gen_length, n)
        for _ in range(n):
            # 每轮分片长度 = 基础长度 + 1(如果还有余数)
            slice_len = floor + 1 if rem > 0 else floor
            yield itertools.islice(array, slice_len)
            rem -= 1


if __name__ == '__main__':
    array_ = iter([12, 7, 9, 31, 13, 11, 7, 3])

    print('Generator:')
    print('----------')
    for value in divide_list(array_, 3, gen_length=8):
        print(list(value))

    print('')
    array_ = [12, 7, 9, 31, 13, 11, 7, 3]

    print('List:')
    print('-----')
    for value in divide_list(array_, 3):
        print(value)

修复后运行输出符合预期:

Generator:
----------
[12, 7, 9]
[31, 13, 11]
[7, 3]

List:
-----
[12, 7, 9]
[31, 13, 11]
[7, 3]

内容的提问来源于stack exchange,提问作者Gabe Morris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 07:33:01