Python入门10:高阶函数

一、什么是高阶函数

1.1、高阶函数的概念和作用:

        高阶函数是指 接受函数作为参数 或者 返回函数 作为结果的函数。它在函数式编程中是一个重要概念(函数式编程(Functional Programming FP )是一 种编程范式,它将计算视为数学函的求值,并且避免使用可变数据结构和 改变状态的操作。函数式编程的核心思想是将函数作为程序的基本构建块, 强调不可变性和纯函数的使用)。

1.2、高阶函数的特点:

(1)、接受一个或多个函数作为输入参数:这意味着你可以将函数作为参数传 递给另一个函数。

  (2)、返回一个函数作为输出:这意味着函数可以返回另一个函数。

二、当参数为一个函数的情况

案例:

# 需求:定义一个函数,带两个整数类型的参数
# 该函数的功能是把两个 参数整理之后 做求和计算,并把结果返回
非高阶函数的写法:
def my_function(num1,num2):# 对传入的两个参数进行平方处理new_num1 = num1**2new_num2 = num2**2# 对处理后的文件进行求和操作,并返回return new_num1+new_num2
print(my_function(3,4))

非高阶函数写法的弊端:

        由于题目的需求的不确定性,针对于“参数整理之后”没有明确的规定,在上面的案例中,我们对传入的两个参数进行了平方再求和的操作,但是实际上有些时候,我们不同的用户调用函数时可能进行不同的处理,比如张三要对这两个数字求绝对值再求和呢?就不得吧求平方的代码改为求绝对值的代码,这样的话函数的用途就很有限了。那么我们怎么样设计才能够不管调用者想对他进行什么操作,而不用改变函数体内的代码呢,当然可以,这个时候我们就需要使用函数作为参数实现了。

高阶函数的写法:

1、当行为函数是自定义时:

# 定义行为函数
def do_function(number):return number * 10
# 注意:在参数中传入函数时不需要加(),加上小括号,表示的是调用函数,不是参数
def my_function(num1,num2,function):""":param num1: 传入第一个数字的参数:param num2: 传入第二个数字的参数:param function: 传入你想要进行的函数操作:return: 返回值是对传入的数字进行处理后求和计算"""return function(num1) + function(num2)
# 调用函数:调用函数在传入函数时不需要加(),加上小阔号表示的是调用函数,不是传参
print(my_function(1,2,do_function))

2、当行为函数是内置模块的函数时:

def my_function(num1,num2,function):""":param num1: 传入第一个数字的参数:param num2: 传入第二个数字的参数:param function: 传入你想要进行的函数操作:return: 返回值是对传入的数字进行处理后求和计算"""return function(num1) + function(num2)# 导入math模块进行先求根再进行操作
import math
# 对参数进行求平方根再求和
print(my_function(100, 4, math.sqrt))
# 对参数进行阶乘操作后求和
print(my_function(2, 4, math.factorial))

3、传入的函数只有一句话时:可以使用lambda表达式:

# 刚刚求和的函数:
my_function = lambda num1, num2,function: function(num1) + function(num2)
# 行为参数:
do_function = lambda number: number * number
# 调用函数并输出
print(my_function(1, 2, do_function))

4、总结:

(1)、当定义函数时,函数的参数是一个函数,那么定义的这个函数可以称为 高阶函数。
(2)、调用高阶函数时需要特别注意,由于高阶函数中参数类型是个函数,因此在进行调用时,我们只需要传递函数的名字即可,而不是进行函数调用。
(3)、函数作为参数的类型时,可以是内置的函数,如abs ,也可以是其它模块 下的函数,如sqrt ,也可以是自定义的函数,如 num_num ,像上面代码中 num_num函数的函数体只有一行代码,可以用 lambda 表达式的方式写。
5、当参数有两个函数时:
# 传入math模块
import math
# 定义高阶函数
def self_fuc(num1,num2,function1,function2):
# 对第一个参数乘10,对第二个参数阶乘操作,再求和return function1(num1) + function2(num2)
# 调用函数:传入两个行为函数
print(self_fuc(1, 2, lambda x: x * 10, math.factorial))

三、当返回值是一个函数的时候

def out_function(*args):print("我是外部函数!")def inner_function(number):sum = 0for i in args:sum += iprint("我是内部函数里面的number,传入的值为:",number)return f'累加结果为:{sum}'# 返回值为内部函数,不需要加(),加上表示调用函数return inner_function
# 返回为地址:因为返回的内部函数的名字,打印的为地址
print(out_function(2,3,4))
# 外部函数返回为内部函数的inner_function,后面的括号表示的inner_function(666)
print(out_function(2,3,4)(666))

四、常见的Python内置高阶函数

4.1、map函数    

map() 函数 接受一个函数 一个可迭代对象 作为参数,将函数应用于可迭代 对象的每个元素,并 返回一个新的迭代器
参数 1 :要传入进行处理的函数名
参数 2 :一个可以操作的数据集或者序列或者是可迭代对象
简单点可以理解为:把参数 2 中的每个元素拿出来,放到参数 1 的函数中去处 理一遍,再返回到一个新的数据集中去。
案例:
# 导入math模块
import math
# 定义一个可迭代数据
numbers = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 调用高阶函数map()并且传入参数,使用sqrt函数对每个数据求算数平方根
map_res = map(math.sqrt, numbers)
print(map_res)
# 由于map函数返回是一个迭代器对象,直接打印的话不够直观
# 因此使用list函数给它进行转化一下输出更直观
print(list(map_res))

4.2、reduce函数

reduce() 函数位于 functools 模块中,它接受 一个函数 和一个 可迭代对 象 作为参数, 函数必须接受两个参数 。reduce() 会将函数依次应用于可迭代 对象的元素, 返回一个单一的结果
# 导入包
import functools
def my_fc(x,y):print("x的值:",x)print("y的值:",y)return x + y
# 定义要操作的可迭代数据
my_list = [1,2,3,4,5]
# 调用reduce函数
res = functools.reduce(my_fc,my_list)
print(res)

4.3、filter函数

filter() 函数接受一个函数和一个可迭代对象作为参数。 filter() 过滤 掉那些函数返回False 的元素,返回一个新的迭代器
# 定义行为参数
def my_function(x):if x > 10:return x
# 定义要处理的可迭代数据
num_list = [1,2,3,4,5,10,20,30,40,50]
# 调用filter函数
res = filter(my_function, num_list)
print(list(res))

4.4、sorted函数

sorted() 函数可以对任何可迭代对象进行排序,并返回一个新的列表。它接受一个key 参数,该参数可以是一个函数,用于指定排序的依据。
stu = [{"name" : "jack","age" : 20},{"name" : "tom","age" : 19},{"name" : "lucy","age" : 19},
]
# 先根据年龄排序,如果年龄相同,再根据名字排序
new_stu = sorted(stu, key=lambda x:(x["age"],x["name"]),reverse=True)
print(new_stu)

4.5、any函数和all函数

any() :如果可迭代对象中至少有一个元素为 True ,则返回 True
all() :如果可迭代对象中所有元素都为 True ,则返回 True
numbers = [1,2,3,4,5,0]
# 是否有非0元素:
is_true = any(numbers)
print(is_true)
# 是否没有0元素
is_true1 = all(numbers)
print(is_true1)

4.6、zip函数

zip() 函数接受多个可迭代对象作为参数,将它们组合成一个迭代器,每个元素是一个元组,包含来自每个可迭代对象的对应元素。
names = ("李小妹","帅哥","张三","tom")
ages = [23,24,20]
# 组合成一个列表
res = list(zip(names,ages))
print(res)
# 组合成一个字典
res1 = dict(zip(names,ages))
print(res1)
# 组合成一个元组
res2 = tuple(zip(names,ages))
print(res2)# 如果合成后还有一个可迭代对象的元素没有匹配,那么将会自动舍弃

4.7、enumerate函数

enumerate() 函数接受一个可迭代对象和一个可选的起始索引,返回一个迭代器,每个元素是一个元组,包含索引和对应的值。
names = ["李小妹","帅哥","张三","tom"]
res = enumerate(names,start=0)
# 只能转化为list
print(list(res))
print(dict(res))
print(tuple(res))
print(set(res))

五、高阶函数的练习

假设你是一家电商公司的数据分析师,需要对销售数据进行分析。你有一个 包含多个订单信息的列表,每个订单信息是一个字典,包含订单ID 、客户ID、订单金额和订单日期。你需要完成以下任务:
1. 筛选出订单金额大于 1000 元的订单
2. 计算每个订单的折扣金额(折扣率为 10%
3. 计算所有订单的总金额
4. 找出订单金额最高的订单
任务要求:
1. 筛选出订单金额大于 1000 元的订单
使用 filter 函数筛选出订单金额大于 1000 元的订单。
将结果存储在变量 high_value_orders 中。
2. 计算每个订单的折扣金额(折扣率为 10%
使用 map 函数计算每个订单的折扣金额。
将结果存储在变量 discounted_orders 中,每个订单字典中增加
一个 discount 键,值为折扣金额。
3. 计算所有订单的总金额
使用 map 函数提取所有订单的金额。
使用 reduce 函数计算所有订单的总金额。
将结果存储在变量 total_amount 中。
4. 找出订单金额最高的订单
使用 max 函数和 key 参数找出订单金额最高的订单。
将结果存储在变量 highest_amount_order 中。
from functools import reduce
# 数据
orders = [{"order_id": 1, "customer_id": 101, "amount": 1200,"date": "2024-01-01"},{"order_id": 2, "customer_id": 102, "amount": 800,"date": "2024-01-02"},{"order_id": 3, "customer_id": 103, "amount": 1500,"date": "2024-01-03"},{"order_id": 4, "customer_id": 104, "amount": 950,"date": "2024-01-04"},{"order_id": 5, "customer_id": 105, "amount": 1800,"date": "2024-01-05"}
]
# 1. 筛选出订单金额大于1000元的订单
high_value_orders = list(filter(lambda order:
order["amount"] > 1000, orders))
# 2. 计算每个订单的折扣金额(折扣率为10%)
discounted_orders = list(map(lambda order: {**order,
"discount": order["amount"] * 0.1}, orders))
# 3. 计算所有订单的总金额
amounts = list(map(lambda order: order["amount"], orders))
total_amount = reduce(lambda x, y: x + y, amounts)
# 4. 找出订单金额最高的订单
highest_amount_order = max(orders, key=lambda order:
order["amount"])
# 输出结果
print("订单金额大于1000元的订单:", high_value_orders)
print("每个订单的折扣金额:", discounted_orders)
print("所有订单的总金额:", total_amount)
print("订单金额最高的订单:", highest_amount_order)

六、递归函数的引入

如果一个函数在执行过程中调用自身,那么这个函数就可以称为递归函数。 也就是在函数体中调用自己。
递归函数的特点:
1 、函数体中调用自己
2 、有一个条件作为出口。不然一直自己调用自己层层套下去就成死循环 了,所以必须要有个条件终止。

阶乘案例:、

def fbnq(n):if n == 1:return 1else:return n * fbnq(n-1)
print(fbnq(4))

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

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

相关文章

Android ScrollView嵌套X5WebView大片空白问题

scrollview嵌套后webview的高度不可控。留有大片空白。 注:官方不建议scrollview嵌套webview 最好让webview自身滚动 解决方案: act_news_detail_wv.setWebViewClient(new WebViewClient() {Overridepublic void onPageFinished(WebView webView, Str…

浅谈云计算12 | KVM虚拟化技术

KVM虚拟化技术 一、KVM虚拟化技术基础1.1 KVM虚拟化技术简介1.2 KVM虚拟化技术架构1.2.1 KVM内核模块1.2.2 用户空间工具(QEMU、Libvirt等) 二、KVM虚拟化技术原理2.1 硬件辅助虚拟化2.2 VMCS结构与工作机制 三、KVM虚拟化技术面临的挑战与应对策略3.1 性…

GO:GO程序如何处理缓存加载和大数据缓存

如果我们会在程序启动时,需要加载所有数据,最简单的方式就是程序启动,通过轮训从数据库拉取所有数据,并写入到本地缓存中。 问题:数据量较大的时候,程序加载慢,启动时间长,遇到问题不…

【优选算法篇】:分而治之--揭秘分治算法的魅力与实战应用

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:优选算法篇–CSDN博客 文章目录 一.什么是分治算法1.分治算法的基本概念2.分治算法的三个步…

【人工智能】从Keras到TensorFlow 2.0:深入掌握Python深度学习技术

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着人工智能技术的迅猛发展,深度学习作为其核心分支,已在图像识别、自然语言处理、语音识别等…

OpenAI Whisper:语音识别技术的革新者—深入架构与参数

当下语音识别技术正以前所未有的速度发展,极大地推动了人机交互的便利性和效率。OpenAI的Whisper系统无疑是这一领域的佼佼者,它凭借其卓越的性能、广泛的适用性和创新的技术架构,正在重新定义语音转文本技术的规则。今天我们一起了解一下Whi…

MATLAB学习笔记-table

table 的每一列具有固定的数据类型。如果要让表的所有单元格都可以任意填充,就得让每一列都是 cell 类型,这样表中每个单元格都是“一个元胞”。创建时可以先构造一个 空 cell 数组(大小为行数列数),再用 cell2table 转…

Spring Boot教程之五十六:用 Apache Kafka 消费 JSON 消息

Spring Boot | 如何使用 Apache Kafka 消费 JSON 消息 Apache Kafka 是一个流处理系统,可让您在进程、应用程序和服务器之间发送消息。在本文中,我们将了解如何使用 Apache Kafka 在 Spring Boot 应用程序的控制台上发布 JSON 消息。 为了了解如何创建 …

python+playwright自动化测试(一):安装及简单使用,截图录屏

目录 基本使用 浏览器调用 启用浏览器 创建窗口对象 访问URL 页面的刷新、返回、前进 关闭 截图、录屏、保存pdf 截图 录屏 保存为pdf 设置窗口大小 调试模式 手机模式及new_context的更多参数 手机模式 new_context的其他参数 设置语言和时区 设置和修改位置…

初识C++(二)

六、引用 引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。 通俗地讲,可以理解为一个人能够拥有多个称呼,这些所有的称呼都是表示这一…

上海市计算机学会竞赛平台2024年12月月赛丙组查找 404

题目描述 Eve 有一个字符串 SS,该字符串仅由字符 *、4 和 0 组成。字符 * 可以被替换为 4 或 0。 Eve 想要计算在所有可能通过替换 * 生成的字符串中,包含子序列 404 的总数。由于这个数字可能非常大,你需要其输出模 10971097 的结果。 例…

【RedisStack】Linux安装指南

【RedisStack】Linux安装指南.md 前言下载解压创建启动文件设置密码把密码设置到环境变量启动/停止相关命令测试&验证官网资料参考资料 前言 Redis Stack是使用Redis的最佳起点。我们将我们必须提供的最好的技术捆绑在一起,形成一个易于使用的软件包。Redis St…

达梦8-DMSQL程序设计学习笔记1-DMSQL程序简介

1、DMSQL程序简介 DMSQL程序是达梦数据库对标准SQL语言的扩展,是一种过程化SQL语言。在DMSQL程序中,包括一整套数据类型、条件结构、循环结构和异常处理结构等,DMSQL程序中可以执行SQL语句,SQL语句中也可以使用DMSQL函数。 DMSQ…

STM32 FreeRTOS 基础知识

多任务处理 内核是操作系统的核心组件。诸如 Linux 这样的操作系统采用的内核, 看似允许用户同时访问计算机。很明显,多个用户可以同时执行多个程序。 每个执行程序都是受操作系统控制的任务(或线程)。如果一个操作系统能够以这…

商用车电子电气零部件电磁兼容条件和试验(2)—术语和定义

写在前面 本系列文章主要讲解商用车电子/电气零部件或系统的传导抗干扰、传导发射和辐射抗干扰、电场辐射发射以及静电放电等试验内容及要求,高压试验项目内容及要求。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) 目录 商用车电子电气…

计算机视觉与深度学习 | 使用深度学习来训练基于视觉的车辆检测器(matlab源码-faster RCNN)

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== faster RCNN训练一个深度学习车辆检测器 下载预训练检测器加载数据集创…

T-SQL编程

目录 1、T-SQL的元素 1.1 标识符 1. 常规标识符 2. 分隔标识符 1.2 变量 1. 全局变量 2. 局部变量 1.3 运算符 1. 算数运算符 2. 赋值运算符 3. 位运算符 4. 比较运算符 5. 逻辑运算符 6. 字符串连接运算符 7. 一元运算符 8. 运算符的优先级和结合性 1.4 批处…

如何将原来使用cmakelist编译的qt工程转换为可使用Visual Studio编译的项目

将原来使用CMakeLists.txt编译的Qt工程转换为可使用Visual Studio编译的项目,可以通过以下步骤实现: 一、准备阶段 安装必要的软件: 确保已安装Visual Studio,并选择了C开发相关的组件。安装CMake,并确保其版本与Qt和…

js中的Object.defineProperty()详解

文章目录 一、Object.defineProperty()二、descriptor属性描述符2.1、数据描述符2.2、访问器描述符2.3、descriptor属性2.3.1、value2.3.2、writable2.3.3、enumerable (可遍历性)2.3.4、configurable (可配置性) 三、注意事项 一…

【搭建JavaEE】(2)Tomcat安装配置和第一个JavaEE程序

Tomcat–容器(Container) 下载 Apache Tomcat - Welcome! 下载完成 请求/响应 结构 测试 查看Jdk版本 改端口号localhost8080–>8099 学学人家以后牛逼了可以用自己名字当文件夹名 配置端口8099 找到server文件 用记事本打开 再打开另一个logging文件 ”乱码解决“步骤&…