Search code examples
pythonlambdadeferred-loading

Lambda or functools.partial for deferred function evaluation?


Let's say we have a basic function:

def basic(arg):
    print arg

We need to defer the evaluation of this function in another function. I am thinking about 2 possible ways:

  1. Using lambdas:

    def another(arg):
        return lambda: basic(arg)
    
  2. Using functools.partial

    from functools import partial
        def another(arg):
            return partial(basic, arg)
    

Which of these approaches is preferred and why? Is there another way of doing this?


Solution

  • Lambdas don't store data which is not in its argument. This could lead to strange behaviors:

    def lambdas(*args):
        for arg in args:
            yield lambda: str(arg)
    
    one, two, three, four = lambdas(1, 2, 3, 4)
    print one(), two(), three(), four()
    

    Expected output

    1 2 3 4
    

    Output

    4 4 4 4
    

    This happens because the lambda didn't store the arg value and it went through all the elements of args, so now arg is always 4.

    The preferred way is to use functools.partial, where you are forced to store the arguments:

    from functools import partial
    
    def partials(*args):
        for arg in args:
            yield partial(str, arg)
    
    one, two, three, four = partials(1, 2, 3, 4)
    print one(), two(), three(), four()
    

    Expected output

    1 2 3 4
    

    Output

    1 2 3 4