Python 中的柯里化

本文介绍了柯里化在数学和计算机科学中的概念,它将多参数函数转化为单参数函数系列。通过示例展示了Python中函数组合的过程,并探讨了如何进行货币转换。此外,还讨论了如何实现任意参数数量的柯里化函数,通过嵌套函数和累积参数来达到这一目标。

大概的概念

咖喱咖喱

在数学和计算机科学中,柯里化是一种分解函数求值的技术,该函数采用多个参数来求值一系列单参数函数。柯里化也用于理论计算机科学,因为将多参数模型转换为单参数模型通常更容易。

函数的组成

我们定义两个函数 f 和 g 的组合 h

H(X)=G(F(X))

在以下 Python 示例中。

两个函数的组合是一个链接过程,其中内部函数的输出变成外部函数的输入。

def  compose ( g ,  f ): 
    def  h ( x ): 
        return  g ( f ( x )) 
    return  h

我们将在下一个示例中使用我们的 compose 函数。让我们假设,我们有一个温度计,它不能准确工作。可以通过将函数重新调整应用于温度值来计算正确的温度。让我们进一步假设我们必须将温度值从摄氏度转换为华氏度。我们可以通过对这两个函数应用compose来做到这一点:

DEF  celsius2fahrenheit (吨):
    返回 1.8  *+  32 
DEF 重新调整(吨):
    返回 0.9  *-  0.5
转换 = 撰写(重新调整, celsius2fahrenheit )
打印(转换(10 ), celsius2fahrenheit (10 ))

输出:

44.5 50.0

两个函数的组合一般是不可交换的,即 compose(celsius2fahrenheit, readjust) 不同于 compose(readjust, celsius2fahrenheit)

convert2  = 撰写(celsius2fahrenheit , 重新调整)
打印(convert2 (10 ), celsius2fahrenheit (10 ))

输出:

47.3 50.0

convert2 不是我们问题的解决方案,因为它不是重新调整温度计的原始温度,而是转换后的华氏温度值!

示例货币转换

魔术函数一章中,我们有一个关于货币转换的练习。

用任意参数“组合”

compose我们刚刚定义的函数只能用单参数函数复制。我们可以概括我们的函数compose以便它可以处理所有可能的函数,以及使用带有两个参数的函数的示例。

def  compose ( g ,  f ): 
    def  h ( * args ,  ** kwargs ): 
        return  g ( f ( * args ,  ** kwargs )) 
    return  h
def  BMI (体重, 身高):
    返回 体重 / 身高** 2 
def 评估_BMI (bmi ):
    如果 bmi  <  15 :
        返回 “非常严重的体重不足” 
    elif  bmi  <  16 :
        返回 “严重体重不足” 
    elif  bmi  <  18.5 :
        返回 
    体重不足” elif  bmi  <  25 :
        返回 “正常(健康体重)” 
    elif  bmi <  30 :
        返回 “超重” 
    elif  bmi  <  35 :
        返回 “肥胖 I 级(中度肥胖)” 
    elif  bmi  <  40 :
        返回 “肥胖 II 级(严重肥胖)” 
    else 返回 “肥胖 III 级(非常严重肥胖)” 
f  =  compose ( evaluate_BMI ,  BMI )
再次 =  "y"
 再次 ==  "y" : 
    weight  =  float ( input ( "重量(公斤)》)) 
    height  =  float ( input ( "height (m) " )) 
    print ( f ( weight ,  height )) 
    again  =  input ( "Another run? (y/n)" )

输出:

正常(健康体重)

带有任意数量参数的柯里化函数

一个有趣的问题仍然存在:如何将函数柯里化为任意且未知数量的参数?

我们可以使用嵌套函数来“压缩”(累积)参数。我们需要一种方法来告诉函数计算并返回值。如果使用参数调用函数,则这些函数将被柯里化,正如我们所说的。如果我们不带任何参数调用函数会怎样?是的,这是告诉函数我们最终想要结果的绝妙方法。我们还可以使用累积值清理列表:

def  arimean ( * args ): 
    return  sum ( args )  /  len ( args ) 
def  curry ( func ): 
    # 保留咖喱函数的名称:
    curry __curried_func_name__  =  func __name__ 
    f_args ,  f_kwargs  =  [],  {} 
    def  f ( * args ,  ** kwargs ):
        非本地 f_args ,  f_kwargs 
        if args  kwargs :
            f_args  +=  args 
            f_kwargs update ( kwargs ) 
            return  f 
        else : 
            result  =  func ( * f_args ,  * f_kwargs ) 
            f_args ,  f_kwargs  =  [],  {} 
            return  result 
    return  f 
curried_arimean  =  curry ( arimean ) 
curried_arimean ( 2 )( 5 )( 9 )(4 ,  5 ) 
# 继续柯里化:
curried_arimean ( 5 ,  9 ) 
print ( curried_arimean ()) 
# 计算
3、4、7的算术平均值print ( curried_arimean ( 3 )( 4 )( 7 )()) 
# 计算
4、3、7的算术平均值print ( curried_arimean ( 4 )( 3 ,  7 )())

输出:

5.571428571428571
4.6666666666666667
4.6666666666666667

让我们将其与原始 arimean 函数的结果进行比较:

打印( arimean ( 2 ,  5 ,  9 ,  4 ,  5 ,  5 ,  9 ))
打印( arimean ( 3 ,  4 ,  7 ))
打印( arimean ( 4 ,  3 ,  7 ))

输出:

5.571428571428571
4.6666666666666667
4.6666666666666667

包括一些打印可能有助于了解发生了什么:

def  arimean ( * args ): 
    return  sum ( args )  /  len ( args ) 
def  curry ( func ): 
    # 保留咖喱函数的名称:
    curry __curried_func_name__  =  func __name__ 
    f_args ,  f_kwargs  =  [],  {} 
    def  f ( * args ,  ** kwargs ):
        非本地 f_args ,  f_kwargs 
        if args  kwargs : 
            print ( "Calling curried function with:" ) 
            print ( "args:" ,  args ,  "kwargs:" ,  kwargs ) 
            f_args  +=  args 
            f_kwargs update ( kwargs ) 
            print ( "Currying the values:" ) 
            print ( "f_args: " ,  f_args ) 
            print ( "f_kwargs:" ,  f_kwargs ) 
            return  f 
        else :
            “呼唤”  + 咖喱__curried_func_name__  +  “与” 打印(f_args , f_kwargs )
            结果 =  FUNC (* f_args , * f_kwargs )
            f_args , f_kwargs  =  [], {}
            返回 结果
    返回 ˚F 
curried_arimean  = 咖喱(arimean )
curried_arimean (2 )(5 )(9 )( 4 , 5 ) 
# 它会继续柯里化:
curried_arimean ( 5 ,  9 ) 
print ( curried_arimean ())

输出:

调用柯里化函数:
args: (2,) kwargs: {}
柯里化值:
f_args: [2]
f_kwargs:{}
调用柯里化函数:
args: (5,) kwargs: {}
柯里化值:
f_args: [2, 5]
f_kwargs:{}
调用柯里化函数:
args: (9,) kwargs: {}
柯里化值:
f_args: [2, 5, 9]
f_kwargs:{}
调用柯里化函数:
args: (4, 5) kwargs: {}
柯里化值:
f_args: [2, 5, 9, 4, 5]
f_kwargs:{}
调用柯里化函数:
args: (5, 9) kwargs: {}
柯里化值:
f_args: [2, 5, 9, 4, 5, 5, 9]
f_kwargs:{}
使用以下命令调用 arimean:
[2, 5, 9, 4, 5, 5, 9] {}
5.571428571428571

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值