【发布时间】:2012-11-20 22:47:15
【问题描述】:
所以我在 Python 中使用柯里化函数,我注意到其中一件事是 functools.partial 返回一个部分对象而不是实际函数。对此让我感到恼火的一件事是,如果我做了以下事情:
five = partial(len, 'hello')
five('something')
然后我们得到
TypeError: len() takes exactly 1 argument (2 given)
但我想要发生的是
TypeError: five() takes no arguments (1 given)
有没有一种干净的方法让它像这样工作?我写了一个解决方法,但它对我的口味来说太老套了(对于带有可变参数的函数还不起作用):
def mypartial(f, *args):
argcount = f.func_code.co_argcount - len(args)
params = ''.join('a' + str(i) + ',' for i in xrange(argcount))
code = '''
def func(f, args):
def %s(%s):
return f(*(args+(%s)))
return %s
''' % (f.func_name, params, params, f.func_name)
exec code in locals()
return func(f, args)
编辑:我认为如果我添加更多上下文可能会有所帮助。我正在编写一个装饰器,它会自动对一个函数进行如下处理:
@curry
def add(a, b, c):
return a + b + c
f = add(1, 2) # f is a function
assert f(5) == 8
我想隐藏 f 是从部分创建的事实(也许是个坏主意:P)。上面的 TypeError 消息给出的消息是可以揭示某物是否为局部的一个示例。我想改变它。
这需要可概括,因此 EnricoGiampieri 和 mgilson 的建议仅适用于特定情况。
【问题讨论】:
-
lambda : len('hello')有什么问题吗?对于functools.partial在lambda之外所做的事情,我总是有点模糊...... -
@mgilson:嗯,它使错误消息变得更糟。你会得到
TypeError: <lambda>() takes 0 positional arguments but 1 was given,而不是TypeError: len() takes exactly 1 argument (2 given)。 -
@mgilson:如果你有两个函数,每个函数的参数数量不同,会发生什么。
lambda需要事先确切知道它将需要多少个 args……当然,除非您将 args 包装在一个元组中并将它们解压缩到lambda -
@mgilson:看看我上面的编辑是否回答了这个问题
-
@abarnert -- 这难道不是 OP 所说的想要的吗? “但我想要发生的是:
TypeError: five() takes no arguments (1 given)”?
标签: python function partial currying