How to bind arguments to given values in Python functions?
Question:
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).
Answers:
You probably want the partial
function from functools.
>>> 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
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
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)
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).
You probably want the partial
function from functools.
>>> 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
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
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)