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

Python中yield生成器对象迭代行为异常的原因解析

生成器迭代行为的疑问与解释

我之前了解到包含yield语句的函数是生成器函数,调用时返回生成器对象而非直接执行函数体,仅在迭代时才会执行函数体。我能理解前两段代码的执行结果,但运行以下代码时输出不符合预期:

def generatorFunc():
    global numList
    numList = range(8)
    for i in numList:
        print(f"id of {i} is {id(i)}")
        yield i*i

mygenerator = generatorFunc()
print(mygenerator)

for i in mygenerator:
    print(f"value of i is {i}")
    print(f"the list is {list(mygenerator)}")

list2 = ([i*i for i in mygenerator])
print(list2)

代码输出为:

<generator object generatorFunc at 0x000001E9692A0CF0>
id of 0 is 140733860812528
value of i is 0
id of 1 is 140733860812560
id of 2 is 140733860812592
id of 3 is 140733860812624
id of 4 is 140733860812656
id of 5 is 140733860812688
id of 6 is 140733860812720
id of 7 is 140733860812752
the list is [1, 4, 9, 16, 25, 36, 49]
[]

我无法理解:为什么print(f"value of i is {i}")仅执行一次,print(f"the list is {list(mygenerator)}")最后才打印?是不是生成器对象被迭代一次后就会耗尽变为空?


问题解释

没错,生成器对象是一次性的迭代器,一旦迭代到末尾就会耗尽,后续再迭代不会返回任何元素。咱们一步步拆解代码的执行流程:

  1. 调用generatorFunc()得到生成器对象mygenerator,此时函数体并未执行,所以先打印出生成器对象的标识<generator object generatorFunc at ...>。
  2. 进入外层for i in mygenerator循环:
    • 第一次迭代生成器,开始执行generatorFunc的函数体:初始化numList为range(8),进入内部for循环取第一个元素0,打印它的id,然后yield 0*0,这个值被赋值给循环变量i,因此执行print(f"value of i is 0")。
    • 接下来执行print(f"the list is {list(mygenerator)}"):list()会一次性迭代生成器的剩余所有元素。此时生成器从之前暂停的位置(i=1)继续执行,依次打印i=1到7的id,同时yield出1、4、9…49这些值,这些值被收集成列表[1,4,9,16,25,36,49],所以这行print要等所有id打印完成、列表生成后,才会输出内容。
    • 至此,生成器已经被list()完全迭代耗尽,处于空状态。
  3. 回到外层的for i in mygenerator循环,由于生成器已经耗尽,循环无法进行下一次迭代,所以print(f"value of i is {i}")只执行了一次。
  4. 最后执行list2 = ([i*i for i in mygenerator]),此时生成器已经没有元素可以迭代,所以得到的是空列表,打印出[]。

内容的提问来源于stack exchange,提问作者Vijith Kumar V

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:24:57