首页 新闻 会员 周边

生成器的例子1

0
[已关闭问题] 关闭于 2026-07-01 17:42
def gen():
    for i in range(5):
        X = int((yield i) or 0) + 10 + i
        print("X:",X)

G = gen()
for a in G:
    print(a)
    G.send(77)

第一阶段:i = 0

  1. for a in G: 隐式调用 next(G),拿到 0
    👉 打印 0
  2. G.send(77) 唤醒生成器,77 赋给 yield
    计算:X = 77 + 10 + 0 = 87
    👉 打印 X: 87
  3. 生成器内部循环,i 变成 1,遇到 yield 1,返回 1
  4. 关键点for 循环的循环体执行完毕,自动进入下一轮,再次隐式调用 next(G)(等价于 send(None))。
    此时 None 赋给 yield,计算:X = 0 + 10 + 1 = 11
    👉 打印 X: 11
  5. 生成器内部循环,i 变成 2,遇到 yield 2,返回 2

第二阶段:i = 2

  1. for 循环拿到刚才返回的 2
    👉 打印 2
  2. G.send(77) 唤醒生成器,计算:X = 77 + 10 + 2 = 89
    👉 打印 X: 89
  3. 生成器内部循环,i 变成 3,遇到 yield 3,返回 3
  4. for 循环自动进入下一轮,调用 next(G)(等价于 send(None))。
    计算:X = 0 + 10 + 3 = 13
    👉 打印 X: 13
  5. 生成器内部循环,i 变成 4,遇到 yield 4,返回 4

第三阶段:i = 4

  1. for 循环拿到刚才返回的 4
    👉 打印 4
  2. G.send(77) 唤醒生成器,计算:X = 77 + 10 + 4 = 91
    👉 打印 X: 91
  3. 生成器内部循环,i 变成 5range(5) 结束,生成器函数自然退出。

第四阶段:报错

  1. for 循环的循环体执行完毕,自动进入下一轮,调用 next(G)
  2. 因为生成器已经结束了,for 循环自动捕获了 StopIteration 异常,正常退出了 for 循环
  3. 关键点:此时代码继续往下执行,来到了你手写的 G.send(77)
  4. 但生成器已经彻底死掉了(耗尽了),对一个已结束的生成器调用 send(),Python 就会无情地抛出 StopIteration
    👉 报错 Traceback... StopIteration
*Tesla*的主页 *Tesla* | 老鸟四级 | 园豆:2040
提问于:2026-07-01 17:42
< >
分享
所有回答(1)
0
0
X: 87
X: 11
2
X: 89
X: 13
4
X: 91
Traceback (most recent call last):
  File "g:\pycode\lists.py", line 10, in <module>
    G.send(77)
StopIteration
*Tesla* | 园豆:2040 (老鸟四级) | 2026-07-01 17:42
def gen():
    # 【内层 for 循环】:属于生成器内部,负责产出数据
    for i in range(5):
        X = int((yield i) or 0) + 10 + i
        print("X:", X)

G = gen()

# 【外层 for 循环】:属于主程序,负责消费(拉取)数据
for a in G:
    print(a)
    G.send(77)

这是一个非常敏锐的问题!你注意到了代码里有两个 for 循环,而且它们的名字都叫 i。
答案是:外层的 for a in G: 先运行,内层的 for i in range(5): 后运行。
为了让你彻底看清它们的“先后顺序”和“嵌套关系”,我们可以把这段代码加上缩进,还原它真实的逻辑层级:
python

编辑



def gen():
    # 【内层 for 循环】:属于生成器内部,负责产出数据
    for i in range(5):
        X = int((yield i) or 0) + 10 + i
        print("X:", X)

G = gen()

# 【外层 for 循环】:属于主程序,负责消费(拉取)数据
for a in G:
    print(a)
    G.send(77)
它们是怎么配合运行的?
这两个 for 循环并不是“谁先跑完,谁再跑”,而是嵌套触发的关系:
外层先启动:主程序执行 for a in G:,它向生成器要第一个数据。
触发内层:生成器收到请求,内层的 for i in range(5): 才开始启动,i 变成 0,然后遇到 yield i,把 0 扔给外层,然后挂起。
外层接管:外层拿到 0,打印 0,然后执行 G.send(77)。
内层继续:send(77) 唤醒了内层,内层从 yield 的地方继续往下跑,计算并打印 X: 87。然后内层循环进入下一轮,i 变成 1,遇到 yield 1,再次把 1 扔给外层,挂起。
循环往复:外层和内层就像齿轮一样,交替咬合运行,直到内层的 range(5) 跑完。


外层 for a in G: 是消费者(在主程序中)。
内层 for i in range(5): 是生产者(在生成器函数中)。
必须是外层先伸手要数据,内层才会开始干活。
支持(0) 反对(0) *Tesla* | 园豆:2040 (老鸟四级) | 2026-07-01 17:45
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册