2 PEP 309: Partial Function Application

#
2 PEP 309: Partial Function Application

The `functools` module is intended to contain tools for functional-style programming.

One useful tool in this module is the `partial()` function. For programs written in a functional style, you'll sometimes want to construct variants of existing functions that have some of the parameters filled in. Consider a Python function `f(a, b, c)`; you could create a new function `g(b, c)` that was equivalent to `f(1, b, c)`. This is called ``partial function application''.

`partial` takes the arguments `(function, arg1, arg2, ... kwarg1=value1, kwarg2=value2)`. The resulting object is callable, so you can just call it to invoke function with the filled-in arguments.

Here's a small but realistic example:

    import functools

    def log (message, subsystem):
        "Write the contents of 'message' to the specified subsystem."
        print '%s: %s' % (subsystem, message)
        ...

    server_log = functools.partial(log, subsystem='server')
    server_log('Unable to open socket')

Here's another example, from a program that uses PyGTK. Here a context-sensitive pop-up menu is being constructed dynamically. The callback provided for the menu option is a partially applied version of the `open_item()` method, where the first argument has been provided.

    ...
    class Application:
        def open_item(self, path):
           ...
        def init (self):
            open_func = functools.partial(self.open_item, item_path)
            popup_menu.append( ("Open", open_func, 1) )

Another function in the `functools` module is the `update_wrapper(wrapper, wrapped)` function that helps you write well-behaved decorators. `update_wrapper()` copies the name, module, and docstring attribute to a wrapper function so that tracebacks inside the wrapped function are easier to understand. For example, you might write:

    def my_decorator(f):
        def wrapper(*args, **kwds):
            print 'Calling decorated function'
            return f(*args, **kwds)
        functools.update_wrapper(wrapper, f)
        return wrapper

`wraps()` is a decorator that can be used inside your own decorators to copy the wrapped function's information. An alternate version of the previous example would be:

    def my_decorator(f):
        @functools.wraps(f)
        def wrapper(*args, **kwds):
            print 'Calling decorated function'
            return f(*args, **kwds)
        return wrapper

See Also:

PEP 309, Partial Function Application
  PEP proposed and written by Peter Harris; implemented by Hye-Shik Chang and Nick Coghlan, with adaptations by Raymond Hettinger.