Search code examples
pythonlambdadecoratorcurrying

How to specify arg position for functool partial()


As per manual, functools partial() is 'used for partial function application which “freezes” some portion of a function’s arguments and/or keywords resulting in a new object with a simplified signature.'

What's the best way to specify the positions of the arguments that one wishes to evaluate?

EDIT

Note as per comments, the function to be partially evaluated may contain named and unnamed arguments (these functions should be completely arbitrary and may be preexisting)

END EDIT

For example, consider:

def f(x,y,z):
    return x + 2*y + 3*z 

Then, using

from functools import partial

both

partial(f,4)(5,6)

and

partial(f,4,5)(6)

give 32.

But what if one wants to evaluate, say the third argument z or the first and third arguments x, and z?

Is there a convenient way to pass the position information to partial, using a decorator or a dict whose keys are the desired arg positions and the respective values are the arg values? eg to pass the x and z positions something like like this:

partial_dict(f,{0:4,2:6})(5)

Solution

  • No, partial is not designed to freeze positional arguments at non-sequential positions.

    To achieve the desired behavior outlined in your question, you would have to come up with a wrapper function of your own like this:

    def partial_positionals(func, positionals, **keywords):
        def wrapper(*args, **kwargs):
            arg = iter(args)
            return func(*(positionals[i] if i in positionals else next(arg)
                for i in range(len(args) + len(positionals))), **{**keywords, **kwargs})
        return wrapper
    

    so that:

    def f(x, y, z):
        return x + 2 * y + 3 * z
    
    print(partial_positionals(f, {0: 4, 2: 6})(5))
    

    outputs:

    32