Recipe 16.4. Associating Parameters with a Function (Currying)
Credit: Scott David Daniels, Nick Perkins, Alex Martelli,
Ben Wolfson, Alex Naanou, David Abrahams, Tracy
Ruggles
Problem
You need to wrap a function (or other callable) to get another
callable with fewer formal arguments, keeping given values fixed for
the other arguments (i.e., you need to curry a
callable to make another).
Solution
Curry is not just a delightful spice used in Asian
cuisineit's also an important programming
technique in Python and other languages:
def curry(f, *a, **kw):
def curried(*more_a, **more_kw):
return f(*(a+more_a), dict(kw, **more_kw))
return curried
Discussion
Popular in functional programming, currying is
a way to bind some of a function's arguments and
wait for the rest of them to show up later. Currying is named in
honor of Haskell Curry, a mathematician who laid some of the
cornerstones in the theory of formal systems and processes. Some
pedants (and it must be grudgingly admitted they have a point) claim
that the technique shown in this recipe should be called
partial application, and that
"currying" is something else. But
whether they're right or wrong, in a book whose
title claims it's a cookbook,
the use of curry in a title was simply
irresistible. Besides, the use of the verb to
curry that this recipe supports is
the most popular one among programmers.The curry function defined in this recipe is invoked
with a callable and some or all of the arguments to the callable.
(Some people like to refer to functions that accept function objects
as arguments, and return new function objects as results, as
higher-order functions.) The
curry function returns a closure
curried that takes subsequent parameters
as arguments and calls the original with all of those parameters. For
example:
double = curry(operator.mul, 2)To implement currying, the choice is among closures, classes with
triple = curry(operator.mul, 3)
callable instances, and lambda forms. Closures are simplest and
fastest, so that's what we use in this recipe.A typical use of curry is to construct callback
functions for GUI operations. When the operation does not merit a new
function name, curry can be useful in creating these
little functions. For example, this can be the case with commands for
Tkinter buttons:
self.button = Button(frame, text='A',Recipe 11.2 shows a
command=curry(transcript.append, 'A'))
specialized subset of "curry"
functionality intended to produce callables that require no
arguments, which are often needed for such GUI-callback usage.
However, this recipe's curry
function is vastly more flexible, without any substantial extra cost
in either complexity or performance.Currying can also be used interactively to make versions of your
functions with debugging-appropriate defaults, or initial parameters
filled in for your current case. For example, database debugging work
might begin by setting:
Connect = curry(ODBC.Connect, dsn='MyDataSet')Another example of the use of curry in debugging
is to wrap methods:
def report(originalFunction, name, *args, **kw):If you are creating a function for regular use, the def
print "%s(%s)"%(name, ', '.join(map(repr, args) +
[k+'='+repr(kw[k]) for k in kw])
result = originalFunction(*args, **kw)
if result: print name, '==>', result
return result
class Sink(object):
def write(self, text): pass
dest = Sink( )
dest.write = curry(report, dest.write, 'write')
print >>dest, 'this', 'is', 1, 'test'
fun form of function definition is more readable and more
easily extended. As you can see from the implementation, no magic
happens to specialize the function with the provided parameters.
curry should be used when you feel the code is
clearer with its use than without. Typically, this use will emphasize
that you are only providing some pre-fixed parameters to a commonly
used function, not providing any separate processing.Currying also works well in creating a "lightweight
subclass". You can curry the
constructor of a class to give the illusion of a subclass:
BlueWindow = curry(Window, background="blue")BlueWindow._ _class_ _ is still
Window, not a subclass, but if
you're changing only default parameters, not
behavior, currying is arguably more appropriate than subclassing
anyway. And you can still pass additional parameters to the curried
constructor.Two decisions must be made when coding a curry implementation, since
both positional and keyword arguments can come in two
"waves"some at currying
time, some more at call time. The two decisions are: do the call-time
positional arguments go before or after the currying-time ones? do
the call-time keyword arguments override currying-time ones, or vice
versa? If you study this recipe's Solution, you can
see I've made these decisions in a specific way (the
one that is most generally useful): call-time positional arguments
after currying-time ones, call-time keyword
arguments overriding currying-time ones. In some
circles, this is referred to as left-left partial
application. It's trivial to code other
variations, such as right-left partial
application:
def rcurry(f, *a, **kw):As you can see, despite the grandiose-sounding terms, this is just a
def curried(*more_a, **more_kw):
return f(*(more_a+a), dict(kw, **more_kw))
return curried
matter of concatenating more_a+a rather than the
reverse; and similarly, for keyword arguments, you just need to call
dict(more_kw, **kw) if you want currying-time
keyword arguments to override call-time ones rather than vice versa.If you wish, you could have the curried function carry a copy of the
original function's docstring, or even (easy in
Python 2.4, but feasible, with a call to
new.function, even in 2.3see the sidebar in
Recipe 20.1) a name that is
somehow derived from the original function. However, I have chosen
not to do so because the original name, and argument descriptions in
the docstring, are probably not appropriate for
the curried version. The task of constructing and documenting the
actual signature of the curried version is also feasible (with a
liberal application of the helper functions from standard library
module inspect), but it's so
disproportionate an effort, compared to
curry's delightfully simple four
lines of code (!), that I resolutely refuse to undertake it.A special case, which may be worth keeping in mind, is when the
callable you want to curry is a Python function
(not a bound method, a C-coded function, a
callable class instance, etc.), and all you need
to curry is the first parameter. In this case,
the function object's _ _get_ _
special method may be all you need. It takes an arbitrary argument
and returns a bound-method object with the first parameter bound to
that argument. For example:
>>> def f(adj, noun='world'):
... return 'Goodbye, %s %s!' % (adj, noun)
...
>>> cf = f._ _get_ _('cruel')
>>> print cf( )
Goodbye, cruel world!
>>> cf
<bound method ?.f of 'cruel'>
>>> type(cf)
<type 'instancemethod'>
>>> cf.im_func
<function f at 0x402dba04>
>>> cf.im_self
'cruel'
See Also
Recipe 11.2 shows a
specialized subset of the curry functionality that is specifically
intended for GUI callbacks; docs for the inspect
module and the dict built-in type in the
Library Reference and Python in a
Nutshell.