Credit: Scott David Daniels, Ben Wolfson, Nick Perkins, and Alex Martelli
You need to tweak a function (or other callable) to get another callable with fewer formal arguments, keeping the original arguments’ given values fixed (i.e., you need to curry a callable to make another).
Curry is not just a spice used in Asian cuisine; it’s also an important technique in Python and other programming languages:
class curry: def _ _init_ _(self, fun, *args, **kwargs): self.fun = fun self.pending = args[:] self.kwargs = kwargs.copy( ) def _ _call_ _(self, *args, **kwargs): if kwargs and self.kwargs: kw = self.kwargs.copy( ) kw.update(kwargs) else: kw = kwargs or self.kwargs return self.fun(*(self.pending + args), **kw)
Popular in functional programming, currying is a way to bind some of
the function’s arguments and wait for the rest of
the arguments 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. The
curry
function defined in this recipe is
called with a callable and some or all of the arguments to the
callable. The curry
function returns a function
that takes subsequent parameters as arguments, and
curry
calls the original with all of those
parameters. This recipe uses a class instance to hold the curried
parameters until they’re needed. For example:
double = curry(operator.mul, 2) triple = curry(operator.mul, 3)
Currying is often implemented with
lambda
forms, but a dedicated class such as the
one provided in this recipe is clearer and more readable. However,
lambda
does have the advantage that the arguments
can be given in any order. If you have such needs and prefer to use
explicit currying classes (or functions) rather than
lambda
, you may have to code other dedicated
adapters for the purpose of renaming or reordering arguments.
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', command=curry(transcript.append, 'A'))
Recipe 9.2 shows a specialized subset of curry functionality intended to produce callables that require no arguments, which are often needed for such GUI-callback usage. However, the recipe shown here is vastly more flexible, without substantial extra cost in 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 wrapping methods:
def report(originalFunction, name, *args, **kw): print "%s(%s)"%(name, ', '.join(map(repr, args) + [k+'='+repr(kw[k]) for k in kw.keys( )]) result = originalFunction(*args, **kw) if result: print name, '==>', result return result class Sink: def write(self, text): pass dest = Sink( ) dest.write = curry(report, dest.write, 'write') print >>dest, 'this', 'is', 1, 'test'
If you are creating a function for regular use, and there is a good
choice for a name, the def fun
form of function
definition is usually 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 will emphasize that you are only providing
parameters to a commonly used function, not providing 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")
Of course, 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.
An alternative implementation of
currying uses lexically nested
scopes, available in Python 2.2 (or 2.1 with from _ _future_ _ import nested_scopes
). The most general way to use
nested scopes for currying is something
like:
def curry(*args, **kwds): def callit(*moreargs, **morekwds): kw = kwds.copy( ) kw.update(morekwds) return args[0](*(args[1:]+moreargs), **kw) return callit
This curries positional arguments from the left and gives named
arguments specified at call time precedence over those specified at
currying time, but these policies are clearly easy to alter. This
version using nested scopes rather than a class is more general,
because it avoids unintentionally capturing certain argument names,
which is inevitable with the class approach. For example, in the
class-based solution in the recipe, imagine needing to
curry
callable with a keyword argument
fun=23
.
Recipe 9.2 shows a specialized subset of the curry functionality that is specifically for GUI callbacks.
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.