Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python lambda's binding to local values

The following code spits out 1 twice, but I expect to see 0 and then 1.

def pv(v) :   print v  x = [] for v in range(2):   x.append(lambda : pv(v))  for xx in x:   xx() 

I expected python lambdas to bind to the reference a local variable is pointing to, behind the scenes. However that does not seem to be the case. I have encountered this problem in a large system where the lambda is doing modern C++'s equivalent of a bind ('boost::bind' for example) where in such case you would bind to a smart ptr or copy construct a copy for the lambda.

So, how do I bind a local variable to a lambda function and have it retain the correct reference when used? I'm quite gobsmacked with the behaviour since I would not expect this from a language with a garbage collector.

like image 930
Hassan Syed Avatar asked May 04 '12 16:05

Hassan Syed


People also ask

Can lambda function access global variables?

Yes, sure. Normal name lookup rules apply.

Can lambda take only one input?

A lambda function can take any number of arguments, but can only have one expression.

How do you call a lambda function in Python?

We can declare a lambda function and call it as an anonymous function, without assigning it to a variable. Above, lambda x: x*x defines an anonymous function and call it once by passing arguments in the parenthesis (lambda x: x*x)(5) .


1 Answers

Change x.append(lambda : pv(v)) to x.append(lambda v=v: pv(v)).

You expect "python lambdas to bind to the reference a local variable is pointing to, behind the scene", but that is not how Python works. Python looks up the variable name at the time the function is called, not when it is created. Using a default argument works because default arguments are evaluated when the function is created, not when it is called.

This is not something special about lambdas. Consider:

x = "before foo defined" def foo():     print x x = "after foo was defined" foo() 

prints

after foo was defined 
like image 74
Steven Rumbalski Avatar answered Sep 28 '22 19:09

Steven Rumbalski