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

编写Python素数打印脚本时a.py与b.py输出差异原因探究

问题描述

我正在编写一个打印素数的Python脚本,以下是两个仅变量名不同的脚本,输出却存在差异:

a.py

def all():
    n = 2
    while True:
        yield n
        n = n + 1

y = all()
number = next(y)
print(number)
y = filter(lambda x: x % number != 0, y)
number = next(y)
print(number)
y = filter(lambda x: x%3 != 0, y)
print(next(y))
y = filter(lambda x: x%5 != 0, y)
print(next(y))
y = filter(lambda x: x%7 != 0, y)

输出:2 3 4 7

b.py

def all():
    n = 2
    while True:
        yield n
        n = n + 1

y = all()
number = next(y)
print(number)
y = filter(lambda x: x % number != 0, y)
num = next(y)
print(num)
y = filter(lambda x: x%3 != 0, y)
print(next(y))
y = filter(lambda x: x%5 != 0, y)
print(next(y))
y = filter(lambda x: x%7 != 0, y)

输出:2 3 5 7

明明变量num和number在y = filter(lambda x: x%3 != 0, y)之后从未被使用,为何该语句之后的输出会出现差异?


解答

这是Python闭包的延迟绑定特性导致的:lambda里引用的变量,不是定义lambda时的固定值,而是等到lambda被实际调用时,才去读取变量的当前值。

拆解a.py的问题:

  1. 创建第一个filter时,lambda x: x % number != 0并没有把当时number的数值2存下来,只是记录了要引用number这个变量。
  2. 紧接着你执行number = next(y),把number的值改成了3。
  3. 后面当第一个filter开始真正工作(调用next(y)触发迭代时),lambda才去取number的值,这时候已经是3了。原本想让第一个过滤掉所有偶数的逻辑,变成了过滤掉所有能被3整除的数。
  4. 所以第三个next(y)拿到的是4:4能通过第一个filter(4%3≠0),也能通过第二个filter(4%3≠0),最终输出4。

再看b.py的正确逻辑:

你用了新变量num来接收next(y)的结果,原来的number变量一直保持初始值2。
当第一个filter开始工作时,lambda读取到的number还是2,正确过滤掉了所有偶数。
第三个next(y)时,生成器跳过了被第一个filter过滤的偶数4,直接拿到5,5能通过第二个filter(5%3≠0),所以输出5。

本质就是a.py复用number变量时,无意间修改了第一个lambda依赖的变量值,而b.py用新变量保留了原变量的初始值,导致两个脚本的过滤逻辑产生差异,最终输出不同。


内容的提问来源于stack exchange,提问作者user1602200

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:25:59