Python生成器调用send()后为何跳过偶数生成步骤?
Python生成器send()后next()输出不符合预期的原因分析与修复
问题原因拆解
你的生成器逻辑中,send()和next()的执行流程导致了看似异常的结果,核心是生成器在恢复执行后的递增步骤没有被正确控制。我们一步步还原调用send(500)后的完整执行流程:
假设生成器已通过几次next()调用,停在incoming = yield start_value(上一次返回的是4,此时start_value为4):
调用
evens_gen.send(500):- 生成器从暂停处恢复,将500赋值给
incoming。 - 执行
if incoming is not None,把start_value设置为500。 - 执行
start_value += 1,start_value变为501。 - 进入下一次循环:
is_even(501)为False,直接执行start_value +=1,变为502。- 再次进入循环:
is_even(502)为True,执行incoming = yield 502,返回502并暂停。
- 生成器从暂停处恢复,将500赋值给
此时调用
next(evens_gen):- 生成器恢复,
incoming被赋值为None(next()等价于send(None))。 - 跳过
start_value = incoming的赋值,执行start_value +=1,变为503。 - 进入下一次循环:
is_even(503)为False,执行start_value +=1,变为504。- 再次进入循环:
is_even(504)为True,执行incoming = yield 504,返回504并暂停。
- 生成器恢复,
本质上,send(500)本身已经返回了502,后续的next()会继续执行生成器逻辑,自然跳过502,返回下一个偶数504。
修复方案
要让send(n)后,next()返回n的下一个偶数,需要调整生成器逻辑,确保接收send的值后,从正确的起点重新检查偶数,避免不必要的递增。
修正代码1(添加continue跳过递增)
def is_even(num): return num % 2 == 0 def get_evens(): start_value = 0 while True: if is_even(start_value): incoming = yield start_value if incoming is not None: start_value = incoming # 接收新值后,跳过本次循环的递增,直接进入下一次检查 continue start_value += 1
修正代码2(重构递增逻辑)
def is_even(num): return num % 2 == 0 def get_evens(): start_value = 0 while True: if is_even(start_value): incoming = yield start_value if incoming is not None: start_value = incoming # 仅在当前值为偶数时递增 start_value += 1 else: start_value += 1
测试结果
evens_gen = get_evens() print(next(evens_gen)) # 0 print(next(evens_gen)) # 2 print(next(evens_gen)) # 4 print(evens_gen.send(500)) # 500 print(next(evens_gen)) # 502 print(next(evens_gen)) # 504
输出完全符合预期:send(500)返回500,后续next()依次返回502、504。
内容的提问来源于stack exchange,提问作者kakou
相关产品推荐
相关产品推荐

