Generator send()函数元素遗漏问题:infinite_palindromes生成器未输出回文数101的原因排查
为什么生成器跳过了回文数101?
让我们一步步拆解你的代码执行流程,就能明白为什么101没有被打印出来:
核心问题:send()调用捕获了101,而非for循环
当你调用pal_gen.send(100)时,这个操作会直接从生成器上次暂停的位置(yield 11之后)恢复执行,并且将num设置为100。接下来生成器的执行路径是:
num += 1变成101is_palindrome(101)返回True,于是执行i = (yield 101)- 此时
yield 101的返回值会被send(100)调用直接捕获,而不是被for循环的迭代器(通过next()调用)获取。for循环只会处理next()调用返回的yield值,所以101不会进入for循环的print("--{0}".format(i))步骤。
完整执行流程梳理
我们从生成器启动开始一步步看:
- 创建生成器
pal_gen后,for循环第一次调用next(pal_gen),生成器从开头执行,直到找到第一个回文数11,执行yield 11,返回给for循环,打印--11。 - 此时
digits=2,原本不触发if块,但你的运行结果显示生成器收到了send(100)——这说明你在迭代过程中(可能是代码误写或手动测试)调用了pal_gen.send(100),而非for循环默认的next()。 send(100)让生成器从yield 11的位置继续:i被赋值为100,num设置为100- 执行
num +=1变成101 - 检测到101是回文数,执行
yield 101,这个值作为send(100)的返回值被返回,但没有被你的代码打印。
- 之后for循环继续调用
next(pal_gen)(等价于send(None)),生成器从yield 101的位置恢复:i被赋值为None,继续执行num +=1变成102- 循环直到找到111,执行
yield 111,这个值被for循环捕获,打印--111
- 此时
digits=3,触发if块,调用pal_gen.close()关闭生成器,之后再调用send()就会抛出StopIteration异常。
修正方案:让for循环捕获所有回文数
如果你希望101被for循环打印,需要避免在生成器正常迭代过程中调用send()(除非你明确知道自己在做什么)。如果你想让生成器跳到某个数值开始,应该在启动迭代前调用send(),而不是在迭代过程中:
def is_palindrome(num): if num // 10 == 0: return False temp = num reversed_num = 0 while temp != 0: reversed_num = (reversed_num * 10) + (temp % 10) temp = temp // 10 return num == reversed_num def infinite_palindromes(): num = 0 while True: if is_palindrome(num): i = (yield num) if i is not None: num = i num += 1 pal_gen = infinite_palindromes() # 先跳到100开始迭代(可选) pal_gen.send(100) for i in pal_gen: print("--{0}".format(i)) digits = len(str(i)) if digits == 3: pal_gen.close() break
这样修改后,生成器会从100开始,找到101并yield给for循环,打印--101,之后继续到111时关闭生成器。
内容的提问来源于stack exchange,提问作者uoay
相关产品推荐
相关产品推荐

