Currying decorator in python

The below implementation is naive, google for "currying python" for more accurate examples.

def curry(x, argc=None):
    if argc is None:
        argc = x.func_code.co_argcount
    def p(*a):
        if len(a) == argc:
            return x(*a)
        def q(*b):
            return x(*(a + b))
        return curry(q, argc - len(a))
    return p

@curry
def myfun(a,b,c):
    print '%d-%d-%d' % (a,b,c)



myfun(11,22,33)
myfun(44,55)(66)
myfun(77)(88)(99)

This one is fairly simple and doesn't use inspect or examine the given function's args

import functools


def curried(func):
    """A decorator that curries the given function.

    @curried
    def a(b, c):
        return (b, c)

    a(c=1)(2)  # returns (2, 1)
    """
    @functools.wraps(func)
    def _curried(*args, **kwargs):
        return functools.partial(func, *args, **kwargs)
    return _curried

Many of the answers here fail to address the fact that a curried function should only take one argument.

A quote from Wikipedia:

In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument (partial application).

Choosing to decorate it with recursion and without co_argcount makes for a decently elegant solution.

from functools import partial, wraps, reduce

def curry(f):
    @wraps(f)
    def _(arg):
        try:
            return f(arg)
        except TypeError:
            return curry(wraps(f)(partial(f, arg)))
    return _

def uncurry(f):
    @wraps(f)
    def _(*args):
        return reduce(lambda x, y: x(y), args, f)
    return _

As shown above, it is also fairly trivial to write an uncurry decorator. :) Unfortunately, the resulting uncurried function will allow any number of arguments instead of requiring a specific number of arguments, as may not be true of the original function, so it is not a true inverse of curry. The true inverse in this case would actually be something like unwrap, but it would require curry to use functools.wraps or something similar that sets a __wrapped__ attribute for each newly created function:

def unwrap(f):
    try:
        return unwrap(f.__wrapped__)
    except AttributeError:
        return f

The source code for curry in the toolz library is available at the following link.

https://github.com/pytoolz/toolz/blob/master/toolz/functoolz.py

It handles args, kwargs, builtin functions, and error handling. It even wraps the docstrings back onto the curried object.