A Lambda Wrinkle

9 AM April 12, 2004

As of Python 2.1, the lambda keyword become a whole lot more useful. Instead of having to pass in each variable value, Python is able to reference variables from the containing containing scope.

For instance, let’s say we have a function called shout(f), which calls its parameter f and prints the result:

>>> def shout(f):
...     print f()
...

In the olden days, if you wanted to shout the numbers 10 through 12, you could pass a lambda function to shout, like this:

>>> for n in range(3):
...     shout(lambda n=n: n+10)
...
10
11
12

While that syntax still works, with Python 2.1 and later, we are able to omit the n=n and write:

>>> for n in range(3):
...     shout(lambda: n+10)
...
10
11
12

However, the two forms of lambda are not quite equivalent. Omitting the n=n causes the lambda to refer to the variable in the stack frame of the function that called the lambda. Consider what happens when we change the value of n after we make the lambda function, but before we call it:

>>> l = []
>>> for n in range(3):
...     l.append(lambda: n+10)
...
>>> for f in l:
...     shout(f)
...
12
12
12
>>>

Putting in the n=n causes the value of n to be copied at the time the lambda function is created, which is exactly what we want in this case:

>>> l = []
>>> for n in range(3):
...     l.append(lambda n=n: n+10)
...
>>> for f in l:
...     shout(f)
...
10
11
12
>>>

I found this little wrinkle while working on a multi-threaded application. One thread was producing lambda functions in a loop, and another thread was calling them – some before the loop was finished, and some after.

By alang | # | Comments (4)
(Posted to Software Development and Python)
© 2003-2006 Alan Green