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

关于一段Python生成器代码的运行逻辑疑问

关于一段Python生成器代码的运行逻辑疑问

嘿,我来帮你拆解这段代码的运行逻辑,搞懂为什么输出是[20, 21, 22, 23]~

首先得抓住两个核心点:

  • 生成器表达式是懒加载的:它不会在定义时立刻计算结果,只有当你真正去遍历它(比如用list()转成列表)的时候才会执行内部逻辑。
  • 生成器里的外部变量是后期绑定的:不是定义生成器那会儿就把变量值固定下来,而是等到迭代的时候才去取变量的当前值。

现在咱们一步步梳理执行流程:

第一步:初始化生成器

先看开头的函数:

def add(n,i):
    return n+i
def test():
    for i in range(4):
        yield i

add()就是简单的两数求和,test()是个生成器函数,调用后会依次产出0、1、2、3这四个值。

然后执行g = test(),此时g只是一个待激活的生成器对象,还没开始产出任何值。

第二步:两次循环重赋值生成器

进入for n in [1,10]的循环:

  • 第一次循环(n=1):g被重新赋值为生成器表达式(add(n,i) for i in g)。注意!这时候这个表达式并没有执行,只是把“要做的操作”记录下来——它知道要遍历当前的g(也就是test()生成器),对每个i调用add(n,i),但这里的n只是引用外部变量,没有绑定具体值。
  • 第二次循环(n=10):g再次被赋值为新的生成器表达式(add(n,i) for i in g)。同样,这个表达式也只是“待命”状态,此时外部的n已经变成10,但生成器里的n依然是引用,没固定值。

第三步:触发生成器计算(关键!)

当执行print(list(g))时,终于要让生成器干活了!这时候会一层层触发迭代:

  1. 最外层是第二次循环创建的生成器,它需要遍历内部的g(也就是第一次循环创建的生成器),对每个i执行add(n,i)——这时候它会取当前的n值,也就是最后一次循环的10。
  2. 遍历第一次循环创建的生成器时,它需要遍历最开始的test()生成器,对每个i执行add(n,i)——这里的n同样取当前的10,而不是之前的1!
  3. 具体计算过程:
    • test()产出0 → 第一次生成器计算add(10, 0)=10 → 第二次生成器计算add(10, 10)=20
    • test()产出1 → add(10,1)=11 → add(10,11)=21
    • test()产出2 → add(10,2)=12 → add(10,12)=22
    • test()产出3 → add(10,3)=13 → add(10,13)=23

最后把这些结果收集成列表,就得到了[20, 21, 22, 23]。

如果想对比验证,你可以把生成器表达式改成列表推导式(比如g = [add(n,i) for i in g]),因为列表推导式是立刻计算的,输出会变成[11,12,13,14]——这就是因为每次循环时n的值被立刻绑定,不会等到最后才取。

备注:内容来源于stack exchange,提问作者user29062757

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:24:29