为何Python生成器代码未按预期输出回文数序列?
生成器
.send()方法输出不符合预期的问题分析 问题场景
学习Python生成器的.send()方法时,期望生成序列11、101、1001、10001...,但实际输出却是11、111、1111、10101...,跳过了预期的中间回文数。
代码示例
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() for i in pal_gen: digits = len(str(i)) pal_gen.send(10 ** (digits))
问题原因
核心问题在于**.send()方法的双重作用**:它既会向生成器传递值,也会触发生成器的一次迭代(等同于调用next()),导致中间生成的回文数被send()消耗,没有被for循环捕获:
- 第一次
for循环自动调用next(pal_gen),生成器找到第一个回文数11并yield,此时生成器暂停在i = (yield num)行。 - 执行
pal_gen.send(100):将100赋值给i,把num设置为100,随后执行num +=1得到101。 - 生成器继续循环,检查到
101是回文数,执行i = (yield num)并yield 101——这个101会作为send()的返回值被返回,但for循环的下一次迭代会再次调用next(pal_gen),导致生成器跳过101,继续递增num直到找到下一个回文数111,才会被for循环的i接收并输出。
解决方法
调整代码逻辑,接收send()的返回值并输出,避免for循环和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() # 启动生成器并获取第一个回文数 current = next(pal_gen) print(current) while True: digits = len(str(current)) # send值并接收返回的下一个回文数 current = pal_gen.send(10 ** digits) print(current)
运行这段代码就能得到预期的11、101、1001、10001...序列。
内容的提问来源于stack exchange,提问作者Nathaniel D'Annunzio
相关产品推荐
相关产品推荐

