Jac*_*din 2 python functional-programming python-3.x
当我做:
def create_funcs():
return (lambda: i for i in range(5))
for f in create_funcs():
print(f())
Run Code Online (Sandbox Code Playgroud)
我得到了预期的:
1
2
3
4
Run Code Online (Sandbox Code Playgroud)
但当我这样做时:
def create_funcs():
return [lambda: i for i in range(5)]
for f in create_funcs():
print(f())
Run Code Online (Sandbox Code Playgroud)
我觉得很奇怪:
4
4
4
4
Run Code Online (Sandbox Code Playgroud)
有谁能解释为什么?
您的lambda函数i从周围范围捕获变量.正如在这个问题中所描述的那样,范围是理解的范围.
您的循环一次迭代生成器中的项目,并在推进生成器之前调用每个项目.当你得到第一个函数时,生成器暂停在一个i0 的状态,这是函数看到的值.当你推进生成器时,它设置i为1,你得到一个抓取该值的函数.发生器"等待"改变,i直到你进入下一个功能.
在列表理解中,您可以立即获得所有功能.但是所有人仍然i在理解范围内引用相同的变量.由于列表理解会一直到最后,i所以在你有机会使用任何函数之前一直到4.
在这两种情况下,lambda都引用了理解范围中的变量.只是在生成器理解中,这个变量在你已经调用了前一个函数之后才会前进.如果存储第一个函数,则可以看到与list-comprehension案例类似的行为,但在再次推进生成器之前不要调用它:
def create_funcs():
return (lambda: i for i in range(5))
gen = create_funcs()
f1 = next(gen)
f2 = next(gen)
print(f1())
print(f2())
Run Code Online (Sandbox Code Playgroud)
输出是
1
1
Run Code Online (Sandbox Code Playgroud)
自从我提出的发电机,i是1,所以无论f1和f2发现价值被调用时.如果你这样做for f in list(create_funcs()),你可以看到同样的事情,迫使生成器一直到列表理解的结尾.