Python 函数式复合和柯里化

Python 函数式复合和柯里化,一些函数式语言的工作原理是将多参数函数语法转化为单参数函数集合,这一过程称为柯里化,它是以逻辑学家Haskell Curry的名字命名的。Haskell Curry从早期概念中发展出了该理论。

柯里化是一种将多参数函数转化为单参数高阶函数的技术。例如函数 f(x,y) -> z,对于给定的两个参数 x 和 y ,该函数会返回 z 值作为结果。可以将 f(x,y) 柯里化为两个函数: f_{c1}(x)->f_{c2}(y) 和 f_{c2}(y) -> z。对于给定的第一个参数值 x,求解函数f_{c1}(y)会返回一个新的单参数函数f_{c2}(y)。第二个函数会接收第二个参数值 y,并返回结果 z。

可以在Python中求解一个柯里化函数:f_c(2)(3)。对第一个参数值2使用柯里化函数,创建一个新函数。随后对第二个参数值3使用这个新函数。

这种做法适用于任何复杂的函数。如果从函数 g(a,b,c)->z 开始,那么可以将其柯里化为函数 g_{c1}(a)-> g_{c2}(b) -> g_{c3}(c) -> z,这是通过递归实现的。首先,对函数 g_{c1}(a) 求值会返回一个带参数 b 和 c 的新函数 g_{c1}^{‘}(b, c)。然后柯里化这个返回的双参数函数并创建函数 g_{c2}(b) -> g_{c3}(b)。

可以用g_c(1)(2)(3)来求解一个复杂的柯里化函数。这种语法形式过于庞大,因此可以使用一些语法糖来将g_c(1)(2)(3)缩减为g(1, 2, 3)这样更容易接受的形式。
下面给出一个Python中的具体示例。例如有一个形式如下的函数:

from pymonad import curry
@curry
def systolic_bp(bmi, age, gender_male, treatment):
    return (
        68.15+0.58*bmi+0.65*age+0.94*gender_male+6.44*treatment
    )

这是一个简单的基于多元回归的心脏收缩压模型。它可以根据体重指数(BMI)、年龄、性别(1代表男性)和既往治疗史(1代表有过治疗)来预测血压。有关该模型及其推导过程的更多信息,请访问:http://sphweb.bumc.bu.edu/otlt/MPH-Modules/BS/BS704_Multivariable/BS704_Multivariable7.html

可以使用systolic_bp()函数处理所有4个参数,如下所示:

>>> systolic_bp(25, 50, 1, 0)
116.09
>>> systolic_bp(25, 50, 0, 1)
121.59

一位BMI为25,且此前没有接受过治疗的50岁男性,其血压会在116左右。第二个示例显示了一位与之类似但接受过治疗的女性,其血压可能在121左右。

由于使用了@curry装饰器,因此可以得到与函数部分求值类似的中间结果。见如下命令片段:

>>> treated = systolic_bp(25, 50, 0)
>>> treated(0)
115.15
>>> treated(1)
121.59

上述示例中,通过对systolic_bp(25, 50, 0)方法进行求值创建了一个柯里化函数,并将其赋给了treated变量。对于给定的患者,BMI、年龄和性别的值通常不会改变。现在可以对剩余的参数使用新的treated函数,根据患者的病史获取不同的血压预测值。

这在某些方面类似于functools.partial()函数。重要的区别在于柯里化创建了一个能以多种方式运作的函数,而functools.partial()函数则会创建一个更具针对性的函数,并且只能用于专门的数值集合。

创建其他一些柯里化函数的示例如下:

>>> g_t= systolic_bp(25, 50)
>>> g_t(1, 0)
116.09
>>> g_t(0, 1)
121.59

这是一个基于初始模型且区分性别的函数。必须提供性别和过往治疗值,以便从模型中得到最终结果。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程