76、Python之函数式编程:柯里化都不懂,别说你会函数式编程

news2024/9/23 16:06:53

引言

很多时候,我们在定义函数处理比较复杂的业务逻辑时,首先是想着遵照“单一职能原则(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())

执行结果:

c1ac3aacf0aba0dbf25c297a248ebc0f.jpeg

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)}')


执行结果:

98f57a44df6df3229387be6988d9d638.jpeg

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('这里有错误,也要打一条日志')

总结

本文简单介绍了柯里化的概念,介绍了柯里化的核心思想以及应用柯里化技术的好处。重点介绍了柯里化的几种常见的应用场景,从而帮助大家更好地将柯里化思想及技术应用与业务实践中。

感谢您的拨冗阅读,希望对您有所帮助。

45182302daf0ed41eca1d37fcf4ff229.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2157943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年双十一有什么好物值得买呢?双十一必买好物清单

双十一买什么犒劳自己既不会浪费钱又可以增添生活的幸福感?以下就整理了五款更适合与秋冬独自生活相伴的好物,精致增加生活氛围感,热爱生活的同时更好的爱自己!努力工作和生活当然也要更好的享受生活,给生活创造更多美…

Vue(14)——组合式API①

setup 特点&#xff1a;执行实际比beforeCreate还要早&#xff0c;并且获取不到this <script> export default{setup(){console.log(setup函数);},beforeCreate(){console.log(beforeCreate函数);} } </script> 在setup函数中提供的数据和方法&#xff0c;想要在…

数据结构和算法之树形结构(2)

文章出处&#xff1a;数据结构和算法之树形结构(2) 关注码农爱刷题&#xff0c;看更多技术文章&#xff01;&#xff01; 三、二叉查找树(接前篇) 二叉查找树&#xff0c;又称二叉搜索树或二叉排序树&#xff0c;是在普通二叉树基础上为了实现快速查找而设计出来的一种树形结…

Fyne ( go跨平台GUI )中文文档-绘图和动画(三)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

继电器测试负载箱的维护和保养方法有哪些?

继电器测试负载箱是用于模拟各种电气负载的设备&#xff0c;广泛应用于继电器、接触器等电气元件的测试和校验。在日常使用中&#xff0c;为确保其正常运行和准确性&#xff0c;以下是一些常见的维护和保养方法&#xff1a; 1. 电源问题&#xff1a;如果电源电压不稳定或波动过…

PD 取电快充协议芯片 支持广泛应用,最高取电电压100W

XSP06是一款支持多协议的受电端取电快充芯片&#xff0c;支持PD2.0/3.0、QC2.0/3.0、华为FCP、三星AFC快充协议。它允许设备通过与快充适配器通信&#xff0c;有效地从适配器或车充等电源诱骗出所需要的电压为自身供电。 特性&#xff1a; 支持电压档位&#xff1a;XSP06支持触…

根据一级分类Id获取专辑标签(内连接,一对多)

文章目录 base_attributebase_attribute_value 1、BaseAttribute2、BaseAttributeValue3、BaseCategoryApiController --》findAttribute()4、BaseCategoryServiceImpl --》findAttribute()5、BaseAttributeMapper6、BaseAttributeMapper.xml 当选择完专辑分类之后&#xff0c;…

如何进行Ubuntu磁盘空间深度清理?

近期使用AutoDL算力云&#xff0c;发现系统盘只有30G&#xff0c;数据盘只有50G&#xff0c;跑一个稍微大一点的模型&#xff0c;马上空间就拉爆了&#xff0c;现在做一个磁盘深度清理操作&#xff0c;看看效果。 清理前磁盘占用如下&#xff1a; 在 Ubuntu 系统中进行磁盘深度…

二、MySQL环境搭建

文章目录 1. MySQL的卸载步骤1&#xff1a;停止MySQL服务步骤2&#xff1a;软件的卸载步骤3&#xff1a;残余文件的清理步骤4&#xff1a;清理注册表&#xff08;选做&#xff09;步骤5&#xff1a;删除环境变量配置 2. MySQL的下载、安装、配置2.1 MySQL的4大版本2.2 软件的下…

Linux环境的JDK安装

1.搜索可用的jdk yum search jdk/(或者是要安装的版本java-11)2.安装需要的版本 yum install java-11-openjdk.x86_643.验证是否安装成功 java -version4.配置环境变量 通过yum安装的默认路径为&#xff1a;/usr/lib/jvm cd /etc/profile.d/ touch java_home.sh vim java_…

Linux线程同步与互斥

&#x1f30e;Linux线程同步与互斥 文章目录&#xff1a; Linux线程同步与互斥 Linux线程互斥 线程锁       互斥量Mutex         初始化互斥量的两种方式         申请锁方式         解除与销毁锁 问题解决及线程饥饿       互斥锁的底…

线性调频信号脉冲压缩并非是一个门信号

如果是频域是门信号&#xff0c;时域是sinc信号&#xff0c;时间越长震荡只会越小。图象是线性卷积做的&#xff0c;肯定没错。

如何写出高收录词的listing文案,先做好这一点

在亚马逊上&#xff0c;关键词是连接买家搜索与产品之间的桥梁&#xff0c;超过80%的购买行为都是通过搜索关键词开始的。因此&#xff0c;文案中包含的精准关键词越多&#xff0c;Listing越能匹配买家的需求&#xff0c;从而提高自然排名并优化广告效果。 亚马逊的收录分为静…

【CSS Tricks】在css中尝试一种新的颜色模型HSL

目录 引言浏览器支持性HSL介绍HSL相较于RGB的优势在哪&#xff1f;HSL在网页设计的应用场景如何用代码转换hslRGB转HSLHSL转RGBHEX格式的互转 总结 引言 本篇不会对rgb颜色模型或是hsl颜色模型的显色原理进行深入的探究&#xff0c;仅从前端开发角度去论述在工作中选择哪种比较…

C/C++指针的前世今生

前言 老早之前就想写这个内容了&#xff0c;打了草稿后闲置了两个月&#xff0c;因为其他事就没再动过这个东西了&#xff0c;今天翻草稿箱的时候发现了它&#xff0c;就把它完善出来&#xff0c;顺便我也学习学习。 正文 指针的前世今生 前面先说一下&#xff0c;故事是随…

【第十七章:Sentosa_DSML社区版-机器学习之异常检测】

【第十七章&#xff1a;Sentosa_DSML社区版-机器学习之异常检测】 机器学习异常检测是检测数据集中的异常数据的算子&#xff0c;一种高效的异常检测算法。它和随机森林类似&#xff0c;但每次选择划分属性和划分点&#xff08;值&#xff09;时都是随机的&#xff0c;而不是根…

前端——实现时钟 附带小例子

创建日期对象 toLocaleDateString() 获取日期 console.log(date.toLocaleDateString()) toLocaleTimeString() 获取时间 console.log(date.toLocaleTimeString()) toLocaleString() 获取日期和时间 console.log(date.toLocaleString()) date.getDay() 获取星期几 周日为…

VisualStudio的“应用代码更改“按钮功能

无意发现这个按钮&#xff0c;因为开发这么多年也没专门尝试这个按钮&#xff0c;于是好奇它的功能。 光标放在按钮上面提示了“应用代码更改”&#xff0c;于是猜想应该是在调试不断开的情况下支持热应用更改。 经过验证&#xff0c;功能确实如同猜想的一样&#xff0c;具体验…

Leetcode 1039. 多边形三角形剖分的最低得分 枚举型区间dp C++实现

问题&#xff1a;Leetcode 1039. 多边形三角形剖分的最低得分 你有一个凸的 n 边形&#xff0c;其每个顶点都有一个整数值。给定一个整数数组 values &#xff0c;其中 values[i] 是第 i 个顶点的值&#xff08;即 顺时针顺序 &#xff09;。 假设将多边形 剖分 为 n - 2 个三…

力扣(leetcode)每日一题 1014 最佳观光组合

题干 1014. 最佳观光组合 给你一个正整数数组 values&#xff0c;其中 values[i] 表示第 i 个观光景点的评分&#xff0c;并且两个景点 i 和 j 之间的 距离 为 j - i。 一对景点&#xff08;i < j&#xff09;组成的观光组合的得分为 values[i] values[j] i - j &#…