Sunday, 7 August 2011

Lists of lambda functions in Python

Lambda functions in Python offer a very convenient way to integrate functional programming in your imperative or object-oriented code. To keep it flexible one may need to generate the code of the lambda function at runtime. To make it work a simple trick is needed.

For the sake of illustration let us take a very simple example. Supposedly, we want to evaluate the sum of every Nth element in the list. We can try to solve the problem by creating a list of lambda functions and then applying it to the list:

functions_list = []
N = 3
for i in xrange(N):
    functions_list.append(lambda x: sum([my_list[j*N + i] 
                       for j in xrange(len(my_list)/N)]))

If we test our functions now, we will get a wrong results:

>>> my_list = range(12)
>>> [f(my_list) for f in functions_list]
[26, 26, 26]


The problem is that interpreter will look for the value of i in the scope, in our case it will find equal to 2 and use for every function in the list.

Using eval() function allows to "embed" the value of i in the functions body at the moment of its creation:

functions_list = []
for i in xrange(N):
    f_str = 'lambda x: sum([my_list[j*%i + %i] ' + \
    'for j in xrange(len(my_list)/%i)])' %( N, i, N)
    functions_list.append(eval(f_str))

And this will lead to the correct solution.


>>> [f(my_list) for f in functions_list]
[18, 22, 26]