Многие ответы здесь не учитывают тот факт, что карри функция должна принимать только один аргумент.
Цитата из Википедии :
В математике и информатике карри - это техника
перевод оценки функции, которая принимает несколько аргументов
(или кортеж аргументов) в оценке последовательности функций,
каждый с одним аргументом (частичное применение).
Выбор декорирования с помощью рекурсии и без co_argcount
делает прилично элегантное решение.
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 _
Как показано выше, написать декоратор uncurry
также довольно тривиально. :) К сожалению, результирующая незакрытая функция будет разрешать любое количество аргументов вместо того, чтобы требовать определенного количества аргументов, что может не соответствовать истинной функции, поэтому она не является истинной обратной величиной curry
. В данном случае истинное обратное будет на самом деле что-то вроде unwrap
, но для этого потребуется curry
, чтобы использовать functools.wraps
или что-то подобное, что устанавливает атрибут __wrapped__
для каждой вновь создаваемой функции:
def unwrap(f):
try:
return unwrap(f.__wrapped__)
except AttributeError:
return f