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

Python中两类gen函数返回lambda的执行结果差异解析求助

为什么两个类似的lambda生成代码会得到不同结果?

嘿,这个问题可是Python里闭包延迟绑定的经典“坑”,我来给你讲明白其中的门道~

先看第一个列表推导式的情况

你写的第一段代码:

def gen(): return [lambda x: x + i for i in range(4)]
print([m(1) for m in gen()])

执行结果是[4, 4, 4, 4],核心原因在于lambda的延迟绑定特性:

  • lambda函数里引用的变量i,并不是在定义lambda的时候就固定下来,而是在实际调用lambda的时候,才会去查找i的当前值。
  • 列表推导式是一次性完成所有lambda的创建的——当整个[lambda x: x+i for i in range(4)]执行完,循环已经跑完,此时变量i的最终值是3(因为range(4)是0、1、2、3)。
  • 所以当你后续调用每个m(1)时,每个lambda都会去取当前的i=3,计算1+3=4,自然四个结果都是4。

再看第二个生成器表达式的情况

第二段代码:

def gen(): return (lambda x: x + i for i in range(4))
print([m(1) for m in gen()])

结果是[1, 2, 3, 4],这要归功于生成器的惰性求值特性:

  • 生成器表达式(lambda x: x+i for i in range(4))不会一次性生成所有lambda,而是每次迭代的时候才生成一个lambda。
  • 当你遍历生成器for m in gen()时,每一次迭代都会对应range(4)里的一个i值:第一次迭代时i=0,此时创建lambda并立刻调用m(1),得到1+0=1;第二次迭代i=1,得到1+1=2,以此类推。
  • 因为每次生成lambda时,i的当前值被捕获到了生成器的迭代上下文里,每个lambda调用时用的都是当时的i值,所以结果符合你的预期。

额外小技巧:如何让第一个列表推导式得到预期结果?

如果想让列表推导式也返回[1,2,3,4],可以用默认参数绑定的方式,把i的值在定义lambda时就固定下来:

def gen(): return [lambda x, i=i: x + i for i in range(4)]
print([m(1) for m in gen()])  # 输出 [1,2,3,4]

这里的i=i会在lambda定义时,把当前循环的i值作为默认参数的值绑定到lambda里,后续调用时就不会再去查找全局的i了。

内容的提问来源于stack exchange,提问作者Aaron.Z

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:18:18