Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable scope inside lambda

Tags:

python

scope

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])      
like image 750
mickeybob Avatar asked Feb 06 '13 21:02

mickeybob


People also ask

How do you increment a variable inside a lambda expression?

If you really need to increment a counter from within a lambda, the typical way to do so is to make the counter an AtomicInteger or AtomicLong and then call one of the increment methods on it. You could use a single-element int or long array, but that would have race conditions if the stream is run in parallel.

What is scope in lambda function?

1 Scope of a Lambda Expression. The body of a lambda expression has the same scope as a nested block. The same rules for name conflicts and shadowing apply. It is illegal to declare a parameter or a local variable in the lambda that has the same name as a local variable.

Can a lambda expression shadow a variable that existed in the enclosing scope?

Lambda parameters are not allowed to shadow variables in the enclosing scopes.

Can we use instance variable in lambda expression?

Instance VariablesA Lambda expression can also access an instance variable. Java Developer can change the value of the instance variable even after its defined and the value will be changed inside the lambda as well.


1 Answers

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.

like image 175
jimwise Avatar answered Oct 23 '22 04:10

jimwise