lambda中的变量范围

mic*_*bob 5 python scope

为什么这段代码打印"d,d,d,d",而不是"a,b,c,d"?如何修改它以打印"a,b,c,d"?

cons = []
for i in ['a', 'b', 'c', 'd']: 
    cons.append(lambda: i)  
print ', '.join([fn() for fn in cons])      
Run Code Online (Sandbox Code Playgroud)

jim*_*ise 6

奇怪的是,这不是一个可变范围问题,而是对python for循环(和python变量)语义的质疑.

如您所料,i在lambda中正确引用i最近的封闭范围中的变量.到现在为止还挺好.

但是,您希望这意味着发生以下情况:

for each value in the list ['a', 'b', 'c', 'd']: 
    instantiate a new variable, i, pointing to the current list member
    instantiate a new anonymous function, which returns i
    append this function to cons
Run Code Online (Sandbox Code Playgroud)

实际发生的是:

instantiate a new variable i
for each value in the list ['a', 'b', 'c', 'd']: 
    make i refer to the current list member
    instantiate a new anonymous function, which returns i
    append this function to cons
Run Code Online (Sandbox Code Playgroud)

因此,您的代码将相同的变量追加i到列表中四次 - 并且在循环退出时,i其值为'd'.

请注意,如果python函数按值获取并返回其参数/返回值的,您将不会注意到这一点,因为每次调用时都会复制内容(或者就此而言,在匿名函数的每次返回时i都会复制)append用...创建lambda.但实际上,python变量总是引用一个特定的对象 - 因此你的四个副本i都是'd'在你的循环结束时引用的.