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

ove*_*nge 6 python functional-programming

什么时候应该以咖喱形式写我的功能?不符合我的想法,需要纠正自己.

作为我学习链接的一部分,这是我从函数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
Run Code Online (Sandbox Code Playgroud)

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

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

我的问题:

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

Tri*_*ion 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)))
Run Code Online (Sandbox Code Playgroud)

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]
Run Code Online (Sandbox Code Playgroud)

现在这还不是那么令人兴奋.它只用类型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
Run Code Online (Sandbox Code Playgroud)

这使

line through zero [-4, -3, -2, -1, 0, 1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

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

替代钻营是:partial,lambdadefault parameters.所以在实践中,currying可能很有用,但如果你愿意,你也可以绕过它.

另请参阅Python中的Currying


Nis*_*ant 5

我能想到柯里化至少有两个优点:

1)它让你的代码(以及你的思维)保持干燥

假设你有一个类似的函数:

def call_me(context, args):
    ...
Run Code Online (Sandbox Code Playgroud)

通过柯里化,你可以获得一个专门的函数,context可以随意使用等等。你不必再次重复上下文。

2)从单个输入函数的角度思考比n参数容易得多;但有时这可能是有争议的。

另请参阅:柯里化和部分应用之间有什么区别?