Variable scope inside lambda

冷暖自知 提交于 2019-12-21 04:57:10

问题


Why does this code print "d, d, d, d", and not "a, b, c, d"? How can I modify it to print "a, b, c, d"?

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

回答1:


Oddly enough, this is not a variable scope problem, but a quesiton of the semantics of python's for loop (and of python's variables).

As you expect, i inside your lambda correctly refers to the variable i in the nearest enclosing scope. So far, so good.

However, you are expecting this to mean the following happens:

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

What actually happens is this:

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

Thus, your code is appending the same variable i to the list four times -- and by the time the loop exits, i has a value of 'd'.

Note that if python functions took and returned the value of their arguments / return values by value, you would not notice this, as the contents of i would be copied on each call to append (or, for that matter, on each return from the anonymous function created with lambda). In actuality, however, python variables are always references to a particular object-- and thus your four copies of i all refer to 'd' by then end of your loop.




回答2:


When you create a closure, the variables that are "closed over" by your lambdas (in this case, i) are bound by name, not value. Therefore, whenever you call your lambdas, they'll use the last value of 'i'.




回答3:


Here's the simple fix you need to make that work:

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



回答4:


'Erics' answer as a comprehension :

 cons =[lambda i= i:i for i in ['a', 'b', 'c', 'd']]   
 print ', '.join([fn() for fn in cons])     


来源:https://stackoverflow.com/questions/14738844/variable-scope-inside-lambda

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!