When thinking about a more general way to partially apply a functions, it would seem to be nice to partially apply to any number of argument, and to handle keyword arguments. As an exercise, we'll build it up step by step.
Let's start by considering the general form of the partial application function. We'll need to provide the function to be partially applied and the arguments to which it should be partially applied. We'll start with positional arguments.
def partial(func, *args):
pass
The next step is to create the function to capture the partial application:
def partial(func, *args):
def newfunc(*fargs):
pass
return newfunc
newfunc
has to take the arguments that are passed to it and combine them with those supplied earlier (to the partial
function), then call the original function with the resulting arguments:
def newfunc(*fargs):
return func(*(args + fargs))
It can simply concatenate the positional arguments (keeping the order correct) since they are in lists.
The partial
function is now:
def partial(func, *args): def newfunc(*fargs): return func(*(args + fargs)) return newfunc
Now we can say:
>>> inc = partial(add, 1)
>>> inc(2)
3
With Keywords
Now we can add keyword arguments. We can make a simple function to build strings:
>>> def wrap(s, prefix='', suffix=''):
... return prefix + s + suffix
...
>>> wrap('hello')
'hello'
>>> wrap('hello', suffix=' world')
'hello world'
>>> wrap('hello', suffix=' world', prefix='>>> ')
'>>> hello world'
We can use partial application to take wrap
and make a greeter function:
>>> greet = partial(wrap, prefix='Hello, ')
>>> greet('Dave')
'Hello, Dave'
>>> greet('Phil', suffix='!')
'Hello, Phil!'
To expand partial
to extend partial application to keyword arguments, we need to add them to the functions, and combine them for the fully applied call. Since they are passed in dictionaries, we can't simply concatenate the way we did with the positional arguments; we need to merge the dictionaries using update
. Our new partial function is now:
def partial(func, *args, **keywords): def newfunc(*fargs, **fkeywords): newkeywords = keywords.copy() newkeywords.update(fkeywords) return func(*(args + fargs), **newkeywords) return newfunc
Page last edited March 08, 2024
Text editor powered by tinymce.