72
votes

I have a number of functions with a combination of positional and keyword arguments, and I would like to bind one of their arguments to a given value (which is known only after the function definition). Is there a general way of doing that?

My first attempt was:

def f(a,b,c): print a,b,c

def _bind(f, a): return lambda b,c: f(a,b,c)

bound_f = bind(f, 1)

However, for this I need to know the exact args passed to f, and cannot use a single function to bind all the functions I'm interested in (since they have different argument lists).

4

4 Answers

122
votes
>>> from functools import partial
>>> def f(a, b, c):
...   print a, b, c
...
>>> bound_f = partial(f, 1)
>>> bound_f(2, 3)
1 2 3
19
votes

You probably want the partial function from functools.

11
votes

As suggested by MattH's answer, functools.partial is the way to go.

However, your question can be read as "how can I implement partial". What your code is missing is the use of *args, **kwargs- 2 such uses, actually:

def partial(f, *args, **kwargs):
    def wrapped(*args2, **kwargs2):
        return f(*args, *args2, **kwargs, **kwargs2)
    return wrapped
3
votes

You can use partial and update_wrapper to bind arguments to given values and preserve __name__ and __doc__ of the original function:

from functools import partial, update_wrapper


def f(a, b, c):
    print(a, b, c)


bound_f = update_wrapper(partial(f, 1000), f)

# This will print 'f'
print(bound_f.__name__)

# This will print 1000, 4, 5
bound_f(4, 5)