博文编程环境
mac 2018
OS: 10.15.5
Python3.8
vscode 1.48.0
介绍
柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。–摘自wiki。
简单介绍就是,当函数需要传入多个参数,通过将其中部分参数赋值为固定值,实现只需传入一个参数就能获取到结果的(函数)技术。
反柯里化(AntiCurrying)则是将柯里化的函数还原。
请看Python3实现代码
Python 实现
柯里化
以下列举了在Python中柯里化的几种实现:
实现函数add,计算两数相加(由于业务场景的原因,其中一个数字固定为10),也就是说函数add的结果返回为:x+10
实现方案一
def add(x,y):
return x+y
def curry(x):
def add(y=10):
return x+y
return add
curry(10)#20
实现方案二
配合functools 实现
def add(x,y):
return x+y
from functools import partial
curry = partial(add,y=10)
curry(10)# 20
实现方案三
配合装饰器 实现
def curry(func):
def wrapper(x,y=10)
return func(x,y)
return wrapper
@curry
def add(x,y):
return x+y
add(10)#20, 为了避免和原函数(add)重名导致版本更迭后兼容问题,推荐柯里化后的函数名为curry,加以区分
实现方案四
配合lambda 实现
def add(x,y):
return x+y
curry = lambda x:add(x,y=10)
curry(10)#20
实现方案五
配合Python库PyMonad 实现
from PyMonad import curry
@curry
def add(x,y):
return x+y
反柯里化
理解了柯里化再理解反柯里化就简单了,还是以上述add()为例:
# 柯里化
def add(x,y):
return x+y
def curry(x):
def add(y=10):
return x+y
return add
curry(10)#20
# 反柯里化
def anti_curry(x,y)
return curry(x)(y)
anti_curry(20,30)# 50
使用场景
最为典型的场景就是接口封装,比如鉴权接口/auth_check;
# auth_check 接口实现如下
def auth_check(params:list,auth_token:str='',server_name:str)->any:
if not auth_token or not server_name:
return False
return True
/auth_check要求传入3个参数,但是由于架构设计升级,本服务的server_name参数统一为advertisement.
正常的实现是逐一更改代码(需要做好历史版本兼容),在不更改auth_check接口的情况下:
if not server_name:
server_name = 'advertisement'
auth_check([param1,param2,param3],'ABXDXX',server_name)
通过柯里化,可以优雅点:
def auth_check_v2(params,auth_token):
try:
from functools import partial
curry = partial(auth_check,server_name='advertisement')
except Exception as e:
raise e
return curry(params,auth_token)
通过柯里化,auth_check 函数的参数由3个转为了2个,而且在不更改auth_check函数本身的情况下封装了新函数auth_check_v2,做了版本兼容。
参考
1、wiki curry:https://zh.wikipedia.org/zh/%E6%9F%AF%E9%87%8C%E5%8C%96
2、functools: https://docs.python.org/zh-cn/3/library/functools.html
3、PyMonad:https://pypi.org/project/PyMonad/