当我这样做时:
def create_funcs():
return (lambda: i for i in range(5))
for f in create_funcs():
print(f())
我得到了预期的结果:
1
2
3
4
但是当我这样做时:
def create_funcs():
return [lambda: i for i in range(5)]
for f in create_funcs():
print(f())
我有一个奇怪的现象:
4
4
4
4
谁能解释一下为什么吗?
最佳答案
您的lambda
函数从周围范围捕获变量i
。如 this question 中所述该范围就是理解的范围。
您的循环一次迭代一个生成器中的项目,并在推进生成器之前调用每个项目。当您获得第一个函数时,生成器将暂停在 i
为 0 的状态,因此这就是函数看到的值。当您推进生成器时,它会将 i
设置为 1,并且您会得到一个获取该值的函数。生成器“等待”更改 i
,直到您前进到下一个函数。
在列表推导式中,您可以一次获得所有函数。但所有这些仍然在理解范围内引用相同的变量i
。由于列表推导式会立即一直走到末尾,因此在您有机会使用任何函数之前,i
会一直走到 4。
在这两种情况下,您的 lambda 都引用理解范围内的变量。只是在生成器理解中,这个变量只有在调用了前一个函数之后才会前进。如果您存储第一个函数,但在再次推进生成器之前不要调用它,您可以看到与列表理解情况类似的行为:
def create_funcs():
return (lambda: i for i in range(5))
gen = create_funcs()
f1 = next(gen)
f2 = next(gen)
print(f1())
print(f2())
输出为
1
1
由于我改进了生成器,i
为 1,因此 f1
和 f2
在调用时都会看到该值。如果您执行 for f in list(create_funcs())
操作,您会看到同样的结果,强制生成器像列表理解一样一直走到末尾。
关于python - lambda 函数的列表或生成器在 Python 中不会返回相同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37283846/