lambda - strange behavior

Rotwang sg552 at hotmail.co.uk
Fri Sep 20 11:52:08 EDT 2013


On 20/09/2013 16:21, Kasper Guldmann wrote:
> I was playing around with lambda functions, but I cannot seem to fully grasp
> them. I was running the script below in Python 2.7.5, and it doesn't do what
> I want it to. Are lambda functions really supposed to work that way. How do
> I make it work as I intend?
>
> f = []
> for n in range(5):
>      f.append( lambda x: x*n )
>
> assert( f[4](2) == 8 )
> assert( f[3](3) == 9 )
> assert( f[2](2) == 4 )
> assert( f[1](8) == 8 )
> assert( f[0](2) == 0 )

This is a common gotcha. In the function "lambda x: x*n" n is a global 
variable, which means that when the function is called it searches 
globals() for the current value of n, which is 4 (since that was its 
value when the for loop ended). There are several ways to define 
functions that depend on the values bound to names at creation time, 
like you're trying to do. One is to use the fact that default function 
arguments are evaluated when the function is created. So this will work:

f = []
for n in range(5):
     f.append(lambda x, n = n: x*n)


Another is to use the fact that arguments passed in function calls are 
evaluated when the function is called. That means that you can define a 
function which takes a parameter as an argument and returns a function 
which depends on that parameter to get the desired behaviour, like this:

f = []
for n in range(5):
     f.append((lambda n: lambda x: x*n)(n))



More information about the Python-list mailing list