5

为什么这段代码打印“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])      
4

4 回答 4

6

奇怪的是,这不是变量范围问题,而是 pythonfor循环(和 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

实际发生的是这样的:

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

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

请注意,如果 python 函数通过 value 获取并返回其参数/返回值的,您不会注意到这一点,因为用) 创建。然而,实际上,python 变量始终是对特定对象的引用——因此你的四个副本都引用到循环结束时。iappendlambdai'd'

于 2013-02-06T21:18:06.397 回答
2

当你创建一个闭包时,被你的 lambda 表达式“关闭”的变量(在本例中为i)是由名称绑定的,而不是值。因此,无论何时调用 lambda,它们都会使用最后一个值“i”。

于 2013-02-06T21:18:48.520 回答
2

这是您完成这项工作所需的简单修复:

cons = []
for i in ['a', 'b', 'c', 'd']: 
    cons.append(lambda i=i: i)  
print ', '.join([fn() for fn in cons])     
于 2013-02-06T22:31:38.343 回答
0

'Erics' 作为理解的回答:

 cons =[lambda i= i:i for i in ['a', 'b', 'c', 'd']]   
 print ', '.join([fn() for fn in cons])     
于 2013-02-06T23:53:13.093 回答