Lambda or functools.partial for deferred function

2020-08-01 05:27发布

问题:

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?

回答1:

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


回答2:

I believe this mostly comes down to personal taste, although functools.partial is believed to be somewhat faster than an equivalent lambda. I prefer to use functools.partial in such situations as in my opinion it makes sense to indicate that we're dealing with a simple partial function application and not a full-blown closure.