我什么时候应该在Python中使用函数currying?

时间:2014-07-22 07:47:44

标签: python functional-programming

When should I write my functions in curried form?与我的想法不符,需要纠正自己。

作为我学习link的一部分,这是我从函数currying中理解的。以下是一个例子:

def curry2(f):
    """Returns a function g such that g(x)(y) == f(x, y)

    >>> from operator import add
    >>> add_three = curry2(add)(3)
    >>> add_three(4)
    """
    def g(x):
        def h(y):
            return f(x, y)
        return h
    return g

在任何应用程序中,如果我知道参数的数量是固定的(比如2个参数)和 函数名称为normalise_range(比如说​​),然后我将定义def normalise_range(x, y):函数,并通过调用normalise_range(x, y)直接在我的应用程序中使用它。

在任何应用程序中,如果我知道,参数的数量是固定的(比如2个参数), 但函数名称是变化的(可以是normalise_range / average /我不知道..), 然后我将使用def curry2(f):,如上所示,它将接受所有带有两个参数的函数(固定)。

我的问题:

  1. 我的理解是否正确?
  2. 如果是,我们可以考虑为可变数量的参数的函数进行求解吗?

2 个答案:

答案 0 :(得分:13)

函数currying的目的是通过更一般的函数轻松获取专用函数。您可以通过在不同时间预先设置一些参数并在之后保持固定来实现此目的。

它与命名无关。在Python中,您可以随时轻松地重命名变量/函数。

示例:

def simple_function(a):
    def line(b=0):
        def compute(x):
            return [a+b * xi for xi in x]
        return compute
    return line

x = range(-4, 4, 1)
print('x {}'.format(list(x)))
print('constant {}'.format(simple_function(3)()(x)))
print('line {}'.format(simple_function(3)(-2)(x)))

给出

x [-4, -3, -2, -1, 0, 1, 2, 3]
constant [3, 3, 3, 3, 3, 3, 3, 3]
line [11, 9, 7, 5, 3, 1, -1, -3]

现在这还不是那么令人兴奋。它只用f(a,b,c)类型的调用替换了f(a)(b)(c)类型的函数调用,甚至可能被认为是Python中不太优雅的样式。

但它允许你这样做:

line_through_zero = simple_function(0)
print('line through zero {}'.format(line_through_zero(1)(x))) # only slope and x

给出了

line through zero [-4, -3, -2, -1, 0, 1, 2, 3]

因此,currying的优势在于您可以获得具有固定参数的专用函数,而不是编写更通用的表单并设置每次调用时固定的参数。

currying的替代方法是:partiallambdadefault parameters。所以在实践中,currying可能很有用,但如果你愿意,你也可以绕过它。

另见Currying in Python

答案 1 :(得分:1)

我想到的至少有两个优点:

1)它保留您的代码(进而使您的思考DRY

假设您具有类似以下功能:

def call_me(context, args):
    ...

通过招惹,您可以获得该context的专用功能,可以将其扔掉,等等。您不必重复上下文。

2)就单个输入函数而言,思考要比n参数容易得多;这有时可能会引起争议。

另请参阅:What is the difference between currying and partial application?