为什么这段代码打印“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])
奇怪的是,这不是变量范围问题,而是 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
因此,您的代码四次将相同的变量附加到列表中 - 到循环退出时,其值为.i
i
'd'
请注意,如果 python 函数通过 value 获取并返回其参数/返回值的值,您不会注意到这一点,因为用) 创建。然而,实际上,python 变量始终是对特定对象的引用——因此你的四个副本都引用到循环结束时。i
append
lambda
i
'd'
当你创建一个闭包时,被你的 lambda 表达式“关闭”的变量(在本例中为i
)是由名称绑定的,而不是值。因此,无论何时调用 lambda,它们都会使用最后一个值“i”。
这是您完成这项工作所需的简单修复:
cons = []
for i in ['a', 'b', 'c', 'd']:
cons.append(lambda i=i: i)
print ', '.join([fn() for fn in cons])
'Erics' 作为理解的回答:
cons =[lambda i= i:i for i in ['a', 'b', 'c', 'd']]
print ', '.join([fn() for fn in cons])