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

为何这段Python代码会抛出StopIteration异常?

问题分析与解决

核心问题

  • 每次调用generate_nos(nos)都会创建全新的生成器实例,而非复用同一个。
  • nos是生成器表达式((i for i in range(10))),这类迭代器是一次性的——迭代到末尾后,无法再产生新值,再次调用next()直接抛出StopIteration。

代码执行流程拆解

  1. 进入while循环,第一次调用next(generate_nos(nos)):
    • 新生成器开始迭代nos,取第一个值0,返回0*2=2,不等于18,循环继续。
  2. 第二次循环,再次调用next(generate_nos(nos)):
    • 又创建新生成器,此时nos已被前一个生成器取走0,现在取1,返回1*2=2,仍不满足条件,循环继续。
  3. 重复上述过程直到第10次循环:
    • 调用next(generate_nos(nos))时,nos已被前面9个生成器取走0-8,现在取9,返回9*2=18,满足if判断条件。
  4. 执行print(next(generate_nos(nos))):
    • 再次创建新生成器,但nos已经迭代完毕(所有值都被取走),调用next()直接触发StopIteration,被外层try-except捕获,输出"StopIteration"。

你的误解纠正

你以为此时调用print(next(generate_nos([0, 1, …, 9])))会输出0,但你的代码里传入的是生成器nos而非列表。如果传入的是列表(比如list(range(10))),每次调用generate_nos都会重新遍历列表,确实能取到0,但nos是一次性生成器,无法重复迭代。

修正方案

要实现预期逻辑(找到值为18的项后,输出生成器的下一个值),需要复用同一个生成器实例:

nos = (i for i in range(10))

def generate_nos(mynos):
    for i in mynos:
        yield i * 2

try:
    gen = generate_nos(nos)  # 仅创建一次生成器
    while True:
        val = next(gen)
        if val == 18:
            print(next(gen))  # 复用同一个生成器取后续值
except StopIteration:
    print("StopIteration")

注:由于nos的最大值是9,生成器gen在返回18(9*2)后,再调用next(gen)会触发StopIteration,最终还是会输出"StopIteration"。如果想让生成器能重复遍历,可将nos改为列表nos = list(range(10))。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:25:18