Elf*_*ЯUs 18 python decorator currying
我正在尝试在python中写一个currying装饰器,我想我已经有了一般的想法,但仍然有一些不正常的情况......
def curry(fun):
cache = []
numargs = fun.func_code.co_argcount
def new_fun(*args, **kwargs):
print args
print kwargs
cache.extend(list(args))
if len(cache) >= numargs: # easier to do it explicitly than with exceptions
temp = []
for _ in xrange(numargs):
temp.append(cache.pop())
fun(*temp)
return new_fun
@curry
def myfun(a,b):
print a,b
Run Code Online (Sandbox Code Playgroud)
虽然对于以下情况,这可以正常工作:
myfun(5)
myfun(5)
Run Code Online (Sandbox Code Playgroud)
对于以下情况,它失败:
myfun(6)(7)
Run Code Online (Sandbox Code Playgroud)
任何有关如何正确执行此操作的指示将非常感谢!
谢谢!
geo*_*org 27
以下实现是天真的,谷歌为"currying python"更准确的例子.
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)
Run Code Online (Sandbox Code Playgroud)
对于源代码curry
的toolz
库可在下面的链接.
https://github.com/pytoolz/toolz/blob/master/toolz/functoolz.py
它处理args,kwargs,内置函数和错误处理.它甚至将文档字符串包裹回到咖喱对象上.
这里的许多答案都未能解决柯里化函数应该只接受一个参数这一事实。
引用维基百科:
在数学和计算机科学中,柯里化是将带有多个参数(或参数元组)的函数的求值转换为求值一系列函数的技术,每个函数都有一个参数(偏应用)。
选择用递归来装饰它,而不是用递归 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 _
Run Code Online (Sandbox Code Playgroud)
如上所示,编写一个装饰器也是相当简单的uncurry
。:) 不幸的是,生成的非柯里化函数将允许任意数量的参数,而不是要求特定数量的参数,这对于原始函数来说可能并非如此,因此它不是 的真正逆curry
。在这种情况下,真正的逆实际上类似于unwrap
,但需要curry
使用或类似的东西为每个新创建的函数functools.wraps
设置属性:__wrapped__
def unwrap(f):
try:
return unwrap(f.__wrapped__)
except AttributeError:
return f
Run Code Online (Sandbox Code Playgroud)