引言
很多时候,我们在定义函数处理比较复杂的业务逻辑时,首先是想着遵照“单一职能原则(SRP)”,尽量拆分为功能单一、足够精简的函数,以便保证代码的可读性和可扩展性。但是,有些逻辑就是没法拆分,很直观的体现,就是有很多个参数,只是搞懂这些参数都有些吃力。
面对这样的窘境,“柯里化”就是一个很好的应对方案。所以,今天我们就来聊一下“柯里化”。
本文的主要内容有:
1、柯里化的基本概念
2、柯里化的好处
3、柯里化的应用场景
柯里化的基本概念
所谓“柯里化(Currying)”是函数式编程中一个重要的概念,它可以将一个接受多个参数的函数转换为一系列仅接受一个参数的函数。
“柯里化”以逻辑学家Haskell Curry命名,这种技术的核心思想是将多元函数分解为多个一元函数(即每个函数仅接受一个参数)。
通过柯里化,我们可以实现逐步传递参数,直到所有参数都被提供,最后得到计算结果。应用这种技术,不仅能使代码更加灵活,还能提高代码的可复用性。
通过代码,简单看下一个柯里化的例子:
# 多元函数
def add(x, y, z):
return x + y + z
# 柯里化
def curried_add(x):
def add_y(y):
def add_z(z):
return x + y + z
return add_z
return add_y
if __name__ == '__main__':
print(add(10, 20, 30))
curried_add(10)(20)(30)
柯里化的好处
成功应用柯里化技术的关键在于,我们能够将多元函数中的参数按照使用的频率进行切分,将相对固化的参数固定下来,从而降低函数调用的复杂度。所以,函数参数的使用频率的准确判断,是进行柯里化实现的关键。
应用柯里化技术的好处主要有:
1、参数预配置:柯里化允许我们可以固定一部分相对固定的参数,从而使得函数的调用变得更加简洁。
2、函数组合:更加容易将多个函数组装在一起,实现函数的链式调用,从而实现更加复杂的函数功能。
3、灵活性增强:基于逐步传递参数,使得我们可以根据需要进行高频、低频函数参数的灵活传递,实现函数调用的灵活性。
4、提高代码的复用性,基于柯里化的设计,可以结合相对固化的参数的有限取值,进行多元函数的部分参数的固化,提高函数的复用性。
柯里化的应用场景
前面说了这么多柯里化的好处,再好,用不起来也是白瞎。所以,接下来,来通过几个使用场景,来帮助大家更好地在实际场景中把柯里化应用起来。
1、参数预配置
在实际开发中,涉及到很多参数的函数,根据需要可以进行预先的部分参数设置,从而提升代码的复用性,以及调用者使用上的便捷性。关于这一点,最常用的方式就是基于柯里化实现了。
我们以模拟http请求的函数为例,进行柯里化设计,演示合理化的使用。
直接看代码:
# 模拟http请求
def http_request(method, url, headers=None, body=None):
return f'method: {method}, url: {url}, headers: {headers}, body: {body}'
def curry_request(base_url):
def with_method(method):
def with_url(path):
def with_headers(headers=None):
def with_body(body=None):
return http_request(method, base_url + path, headers, body)
return with_body
return with_headers
return with_url
return with_method
if __name__ == '__main__':
# 应用柯里化进行统一的配置
# 预配置url的基准路径
api_request = curry_request('http://apis.xxx.com')
# 预配置GET的http请求
get_api_request = api_request('GET')
# 预配置请求具体资源路径
get_user = get_api_request('/user')()
print(get_user())
执行结果:
2、函数组合和管道
通过柯里化,我们可以轻松地把函数进行组合,实现管道式的操作,特别是在数据处理和变换处理中。
def add(x):
return lambda y: x + y
def multiply(x):
return lambda y: x * y
def power(x):
return lambda y: y ** x
if __name__ == '__main__':
# 使用柯里化函数组合
# 实现 y = (x + 10)^2 * 5
num = 10
result = multiply(5)(power(2)(add(10)(num)))
print(result)
3、高阶函数的动态策略
基于柯里化,构建一些高阶函数,可以实现更加灵活的策略选择,比如打折。
# 模拟折扣策略
def discount_strategy(discount):
def actual_amount(amount):
return amount - amount * discount
return actual_amount
if __name__ == '__main__':
# 模拟不同的折扣
# 打九折
ten_percent = discount_strategy(0.1)
# 打骨折
ninty_percent = discount_strategy(0.9)
price = 100
print(f'价格:{price},打九折后,实收:{ten_percent(price)}')
print(f'价格:{price},打骨折后,实收:{ninty_percent(price)}')
执行结果:
4、配置上下文
提前配置一些参数,实现上下文的提前配置,做到复用,比如日志的级别,避免每次打日志都要带level参数:
def logger(level):
def log(msg):
print(f'[{level}] {msg}')
return log
if __name__ == '__main__':
# 柯里化进行日志level的固化
info_logger = logger('INFO')
error_logger = logger('ERROR')
info_logger('这里需要打一条日志')
error_logger('这里有错误,也要打一条日志')
总结
本文简单介绍了柯里化的概念,介绍了柯里化的核心思想以及应用柯里化技术的好处。重点介绍了柯里化的几种常见的应用场景,从而帮助大家更好地将柯里化思想及技术应用与业务实践中。
感谢您的拨冗阅读,希望对您有所帮助。