为什么此代码打印“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])
答案 0 :(得分:6)
奇怪的是,这不是一个变量的范围问题,而是对python的for
循环(以及python变量)语义的质疑。
如您所料,lambda中的i
正确引用最近的封闭范围中的变量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
的值为{{ 1}}。
请注意,如果python函数接受并通过 value 返回其参数/返回值的值,您将不会注意到这一点,因为{{1}的内容 }将在每次调用'd'
时复制(或者,就此而言,在使用i
创建的匿名函数的每次返回时)。但实际上,python变量总是引用到特定对象 - 因此,append
的四个副本在循环结束时都引用lambda
。 / p>
答案 1 :(得分:2)
创建闭包时,lambdas“封闭”的变量(在本例中为i
)受名称限制,而不是值。因此,每当你打电话给你的lambdas时,他们都会使用'i'的最后一个值。
答案 2 :(得分:2)
以下是您需要做的简单修复:
cons = []
for i in ['a', 'b', 'c', 'd']:
cons.append(lambda i=i: i)
print ', '.join([fn() for fn in cons])
答案 3 :(得分:0)
'Erics'的回答是理解:
cons =[lambda i= i:i for i in ['a', 'b', 'c', 'd']]
print ', '.join([fn() for fn in cons])