pythonfunctional-programmingcompositionfunction-composition

Composing functions in python


I have an array of functions and I'm trying to produce one function which consists of the composition of the elements in my array. My approach is:

def compose(list):
    if len(list) == 1:
        return lambda x:list[0](x)
    list.reverse()
    final=lambda x:x
    for f in list:
        final=lambda x:f(final(x))
    return final

This method doesn't seems to be working, help will be appreciated.

(I'm reversing the list because this is the order of composition I want the functions to be)


Solution

  • It doesn't work because all the anonymous functions you create in the loop refer to the same loop variable and therefore share its final value.

    As a quick fix, you can replace the assignment with:

    final = lambda x, f=f, final=final: f(final(x))
    

    Or, you can return the lambda from a function:

    def wrap(accum, f):
        return lambda x: f(accum(x))
    ...
    final = wrap(final, f)
    

    To understand what's going on, try this experiment:

    >>> l = [lambda: n for n in xrange(10)]
    >>> [f() for f in l]
    [9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
    

    This result surprises many people, who expect the result to be [0, 1, 2, ...]. However, all the lambdas point to the same n variable, and all refer to its final value, which is 9. In your case, all the versions of final which are supposed to nest end up referring to the same f and, even worse, to the same final.

    The topic of lambdas and for loops in Python has been already covered on SO.