当前位置: 首页 > article >正文

Python 高阶函数(详解)

        前言:这篇详细讲解了Python中的高阶函数,并且对高阶函数中的重要的内置函数也进行了详解,温馨提醒!篇幅较长可以慢慢观看。

一:高阶函数

只要满足下面的任意一个条件就是高阶函数

  • 1、一个函数的函数名作为参数传给另外一个函数
  • 2、一个函数返回值(return)为另外一个函数(返回为自己,则为递归)

高阶函数的基本概念:

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

高阶函数与普通函数应用场景的区别:

普通函数

        普通函数适用于实现具体的、独立的操作,例如数学运算、文件操作、字符串处理等。它们通常具有明确的输入和输出,处理相对具体的任务。

def square(x):
    return x ** 2

高阶函数

        高阶函数更具抽象性和通用性,可用于封装通用的算法或操作模式。

def square(x):
    return x ** 2
numbers = [1, 2, 3, 4, 5]
squared_numbers = map(square, numbers)
def my_sum():
    def new_my_sum():
        print('123')
    return new_my_sum

my_sum = my_sum()

代码分析(重点,要理解)

        在上面的代码案例中,函数体里面对参数进行了求平方的处理操作,实际情况并不是每个调用者都想对参数进行求绝对值的处理,张三想调用这个函数对参数进行平方处理那怎么办呢?从上面的代码中来看,如果张三想要对参数求平方处理,就不得不把求绝对值的代码改成求平方的代码,如果是这样的话,那这个函数的设计用途就很有限了。那我能不能设计一下,不管调用者想对它进行什么操作,而不用去改变我函数体里面的代码呢?当然可以,这个时候就需要使用函数来作为参数实现了。(高阶函数更灵活,适用的场景也更多)
def my_sum(a,b,han,hen):
    return han(a)+hen(b)

def dz(shu):
    return shu/2

def da(shu):
    return shu*2


print(my_sum(6, 6, da,dz))
print(my_sum(6,6, da,dz()))

注意:其中第二个是错误的(不能带括号)

总结(特别重要):
1 、当定义函数时,函数的参数是一个函数,那么定义的这个函数可以称为高阶函数。
2 、调用高阶函数时需要特别注意,由于高阶函数中参数类型是个函数,因此在进行调用时,我们只需要传递函数的名字即可,而不是进行函数调用。

3 、函数作为参数的类型时,可以是内置的函数,如 abs ,也可以是其它模块下的函数,如sqrt ,也可以是自定义的函数,如 num_num ,像上面代码中num_num函数的函数体只有一行代码,可以用 lambda 表达式的方式写。

lambda表达式的多种使用方式:

def my_sum(a,b,han):
    return han(a)+han(b)
print(my_sum(6, 6, lambda x:x**2))
def da(shu):
    return shu*2
f = lambda x,y,z:(z(x),z(y))
print(f(1, 2, da))

二:python中内置常用高阶函数

1.map函数:
map() 函数接受一个函数和一个可迭代对象作为参数,将函数应用于可迭代对象的每个元素,并返回一个新的迭代器。
参数 1 :要传入进行处理的函数名
参数 2 :一个可以操作的数据集或者序列或者是可迭代对象
eg: 简单点可以理解为:把参数 2 中的每个元素拿出来,放到参数 1 的函数中去处 理一遍,再返回到一个新的数据集中去。
案例:
# map(函数,可迭代对象):把函数作用于可迭代对象,并且返回可迭代对象
def fu(a):
    return a*a
my_list = [1,2,3,4,5]
print(map(fu,my_list))
res = map(fu,my_list)
print(list(res))
2.reduce函数:
reduce() 函数位于 functools 模块中,它接受一个函数和一个可迭代对象作为参数,函数必须接受两个参数。reduce() 会将函数依次应用于可迭代对象的元素,返回一个单一的结果。

eg:reduce(函数,可迭代对象):函数需要两个参数,返回一个单一结果!

from functools import reduce
def fa(x,y):
    # print('x的值为',x)
    # print('y的值为',y)
    return x+y
my_list = [1,2,3,4,5]

res = (reduce(fa,my_list))
print(res)
3.filter函数:

Python 中,filter() 是一个内置的高阶函数,其主要作用是根据指定的条件过滤可迭代对象中的元素,返回一个包含满足条件元素的迭代器。

基本语法:

filter(function, iterable)
  • function:这是一个用于筛选元素的函数,它接受一个参数,并返回一个布尔值(TrueFalse)。如果返回 True,则表示该元素满足条件,会被保留;如果返回 False,则该元素会被过滤掉。这个参数可以是一个普通函数、匿名函数(lambda 函数),也可以为 None
  • iterable:是一个可迭代对象,如列表、元组、字符串、集合等,filter() 函数会对其元素逐个进行筛选。

实例:

1. 使用普通函数进行筛选
def is_even(num):
    return num % 2 == 0

numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter(is_even, numbers)
print(list(even_numbers))

代码解释

  • 定义了一个普通函数 is_even,用于判断一个数是否为偶数。如果是偶数,函数返回 True;否则返回 False
  • 调用 filter(is_even, numbers) 时,filter() 函数会遍历 numbers 列表中的每个元素,并将其传递给 is_even 函数进行判断。
  • 最终,filter() 函数返回一个迭代器,包含了所有偶数元素。使用 list() 函数将迭代器转换为列表并打印,输出结果为 [2, 4, 6]
2. 使用匿名函数(lambda 函数)进行筛选
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))

代码解释

  • 这里使用了一个匿名函数 lambda x: x % 2 == 0 来替代普通函数。匿名函数的功能和上面的 is_even 函数相同,用于判断一个数是否为偶数。
  • filter() 函数的工作方式和前面示例一样,最终返回一个包含偶数元素的迭代器,转换为列表后输出结果同样为 [2, 4, 6]
3. 过滤字符串列表
words = ["apple", "banana", "cherry", "date"]
long_words = filter(lambda word: len(word) > 5, words)
print(list(long_words))

代码解释

  • 定义了一个字符串列表 words
  • 使用匿名函数 lambda word: len(word) > 5 作为筛选条件,该函数用于判断一个字符串的长度是否大于 5。
  • filter() 函数遍历 words 列表中的每个字符串,并根据匿名函数的返回值进行筛选,最终返回一个包含长度大于 5 的字符串的迭代器,转换为列表后输出结果为 ["banana", "cherry"]
4. 当 function 参数为 None
values = [0, 1, False, True, [], [1, 2], '', 'hello']
truthy_values = filter(None, values)
print(list(truthy_values))

代码解释

  • function 参数为 None 时,filter() 函数会将 iterable 中的元素转换为布尔值进行判断。在 Python 中,像 0False、空列表 []、空字符串 '' 等会被视为 False,其他值会被视为 True
  • filter() 函数会过滤掉所有被视为 False 的元素,最终返回一个包含被视为 True 的元素的迭代器,转换为列表后输出结果为 [1, True, [1, 2], 'hello']

注意事项

  • 返回值是迭代器filter() 函数返回的是一个迭代器,而不是一个列表。如果需要多次使用筛选结果,或者需要查看所有元素,可以使用 list() 函数将其转换为列表。但要注意,对于大型数据集,将迭代器转换为列表可能会占用大量内存。
  • 原可迭代对象不会被修改filter() 函数只是根据条件筛选元素,不会对原可迭代对象进行修改。

综上所述,filter() 函数是一个非常实用的工具,可以帮助我们方便地根据特定条件筛选可迭代对象中的元素。

4.sorted函数:
sorted() 函数可以对任何可迭代对象进行排序,并返回一个新的列表。它接受一个key 参数,该参数可以是一个函数,用于指定排序的依据。

1. 多条件排序

fr = [
    {'name': 'boa', 'about': 100},
    {'name': 'bob', 'about': 200},
    {'name': 'boc', 'about': 300},
]
def fr_my(x):
    return -x['about'],x['name']

print(sorted(fr, key=fr_my))
students = [
    {"name": "Alice", "age": 20},
    {"name": "Bob", "age": 18},
    {"name": "Charlie", "age": 20}
]
sorted_students = sorted(students, key=lambda student: (student["age"], student["name"]))
print(sorted_students)

代码解释: 这里的 key 函数返回一个元组 (student["age"], student["name"]),表示先按 "age" 进行排序,如果 "age" 相同,则按 "name" 进行排序。最终输出结果为 [{'name': 'Bob', 'age': 18}, {'name': 'Alice', 'age': 20}, {'name': 'Charlie', 'age': 20}]

2. 自定义排序规则(例如按绝对值排序)

numbers = [-3, 1, -2, 4]
sorted_numbers = sorted(numbers, key=abs)
print(sorted_numbers)

 代码解释: 指定 key 函数为 abs(求绝对值的函数),sorted() 函数会根据每个数的绝对值进行排序,输出结果为 [1, -2, -3, 4]

注意事项

  • 返回值是新列表sorted() 函数会返回一个新的已排序列表,原可迭代对象不会被修改。如果需要对原列表进行原地排序,可以使用列表的 sort() 方法。
  • 元素类型一致性:在排序时,要确保 iterable 中的元素类型是可以相互比较的,否则可能会引发 TypeError 异常。例如,不能直接对包含数字和字符串的列表进行排序。

综上所述,sorted() 函数是一个非常强大且灵活的排序工具,通过合理使用 keyreverse 参数,可以满足各种不同的排序需求。

5.any函数和all函数:

any() 函数接受一个可迭代对象(如列表、元组、集合、字符串等)作为参数,用于检查可迭代对象中是否至少有一个元素的布尔值为 True

工作原理(相当于or)

  • any() 函数会遍历可迭代对象中的每个元素。
  • 对于每个元素,将其转换为布尔值(使用 bool() 函数)。
  • 如果在遍历过程中遇到一个元素的布尔值为 True,则函数立即返回 True,不再继续遍历后续元素。
  • 如果遍历完整个可迭代对象后,没有找到布尔值为 True 的元素,则函数返回 False

示例代码:

# 示例 1:列表中至少有一个元素为 True
numbers = [0, False, 3]
result = any(numbers)
print(result)  # 输出: True,因为 3 转换为布尔值为 True

# 示例 2:列表中所有元素都为 False
empty_list = []
false_list = [0, False, '']
print(any(empty_list))  # 输出: False,空列表中没有元素为 True
print(any(false_list))  # 输出: False,列表中所有元素转换为布尔值都为 False

# 示例 3:字符串
string = "abc"
print(any(string))  # 输出: True,因为字符串中的每个字符转换为布尔值都为 True

# 示例 4:嵌套可迭代对象
nested_list = [[], [0], [False]]
print(any(nested_list))  # 输出: True,因为 [0] 转换为布尔值为 True

all() 函数同样接受一个可迭代对象作为参数,用于检查可迭代对象中的所有元素的布尔值是否都为 True

工作原理(相当于and)

  • all() 函数会遍历可迭代对象中的每个元素。
  • 对于每个元素,将其转换为布尔值(使用 bool() 函数)。
  • 如果在遍历过程中遇到一个元素的布尔值为 False,则函数立即返回 False,不再继续遍历后续元素。
  • 如果遍历完整个可迭代对象后,所有元素的布尔值都为 True,则函数返回 True。需要注意的是,对于空的可迭代对象,all() 函数会返回 True

示例代码:

# 示例 1:列表中所有元素都为 True
numbers = [1, True, 'abc']
result = all(numbers)
print(result)  # 输出: True,因为列表中所有元素转换为布尔值都为 True

# 示例 2:列表中有元素为 False
mixed_list = [1, 0, True]
print(all(mixed_list))  # 输出: False,因为 0 转换为布尔值为 False

# 示例 3:空列表
empty_list = []
print(all(empty_list))  # 输出: True,空列表视为所有元素都为 True

# 示例 4:字符串
string = "abc"
print(all(string))  # 输出: True,因为字符串中的每个字符转换为布尔值都为 True

# 示例 5:嵌套可迭代对象
nested_list = [[1], [2], [3]]
print(all(nested_list))  # 输出: True,因为每个子列表转换为布尔值都为 True

总结

  • any() 函数用于判断可迭代对象中是否至少有一个元素的布尔值为 True
  • all() 函数用于判断可迭代对象中的所有元素的布尔值是否都为 True,空可迭代对象也视为所有元素都为 True

这两个函数在处理条件判断和逻辑检查时非常有用,可以避免手动编写复杂的循环来检查元素的布尔值。

6.zip函数:

*iterables 表示可以传入任意数量的可迭代对象,这些可迭代对象将被 “压缩” 在一起。

工作原理

  • zip() 函数会从每个传入的可迭代对象中依次取出一个元素,组成一个元组,然后将这些元组作为新的迭代器的元素。
  • 当最短的可迭代对象元素被取完时,zip() 函数就会停止迭代,即使其他可迭代对象还有剩余元素。
1.压缩多个可迭代对象
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
tuple1 = (10, 20, 30)
zipped = zip(list1, list2, tuple1)
print(zipped)            #输出地址
print(list(zipped))      

代码解释

  • 这次传入了三个可迭代对象:list1list2tuple1
  • zip() 函数会从这三个可迭代对象中依次取出对应位置的元素,组成三元组。
  • 输出结果为 [(1, 'a', 10), (2, 'b', 20), (3, 'c', 30)]
2.结合 for 循环使用
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
for name, age in zip(names, ages):
    print(f"{name} is {age} years old.")

代码解释

  • zip(names, ages) 会生成一个迭代器,其中每个元素是一个包含姓名和年龄的元组。
  • for 循环会依次从这个迭代器中取出元组,并将元组中的元素分别赋值给 nameage 变量。
  • 最终会依次输出每个人员的姓名和年龄信息。
3.解压缩操作
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
numbers, letters = zip(*pairs)
print(numbers)
print(letters)

代码解释

  • *pairs 是将 pairs 列表中的元素解包作为参数传递给 zip() 函数。
  • zip() 函数会对这些元组进行 “解压缩” 操作,将每个元组中相同位置的元素重新组合成新的元组。
  • 最终 numbers(1, 2, 3)letters('a', 'b', 'c')

注意事项

  • 最短可迭代对象原则zip() 函数会以最短的可迭代对象为准停止迭代。
  • 返回的是迭代器zip() 函数返回的是一个迭代器,而不是列表。如果需要多次使用结果或者查看所有元素,可以使用 list() 函数将其转换为列表,但要注意对于大型数据集,将迭代器转换为列表可能会占用大量内存。

综上所述,zip() 函数是一个非常方便的工具,在处理多个可迭代对象时,可以轻松地将它们的元素进行组合或解组合。

7.enumerate函数:

在 Python 中,enumerate() 是一个实用的高阶函数,常用于在遍历可迭代对象(如列表、元组、字符串等)时同时获取元素的索引和对应的值。

enumerate(iterable, start=0)
  • iterable:必需参数,代表要进行遍历的可迭代对象,例如列表、元组、字符串等。
  • start:可选参数,是一个整数,用于指定索引的起始值,默认值为 0

工作原理

  • enumerate() 函数会接收一个可迭代对象,并返回一个枚举对象,该枚举对象是一个迭代器。
  • 在迭代过程中,每次迭代会生成一个包含两个元素的元组,第一个元素是当前元素的索引(从 start 指定的值开始),第二个元素是可迭代对象中对应位置的元素。
1.指定索引起始值:
fruits = ['apple', 'banana', 'cherry']
for index, fruit in enumerate(fruits, start=1):
    print(f"第 {index} 个水果是: {fruit}")
2.使用enumerate()函数可以很方便地同时获取元素的索引和元素本身。例如,在需要打印列表元素及其位置的时候
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"Index {index}: {fruit}")
3.用于构建字典:可以利用enumerate()函数来构建字典,其中索引作为键,可迭代对象中的元素作为值。
fruits = ["apple", "banana", "cherry"]
fruit_dict = dict(enumerate(fruits))
print(fruit_dict)

注意事项

  • 返回的是迭代器enumerate() 函数返回的是一个枚举对象,它是一个迭代器。如果需要多次使用结果或者查看所有元素,可以使用 list() 函数将其转换为列表,但要注意对于大型数据集,将迭代器转换为列表可能会占用大量内存。
  • 索引是从 start 开始的:要注意根据实际需求设置 start 参数的值,避免索引使用错误。

综上所述,enumerate() 函数是一个非常方便的工具,在需要同时获取可迭代对象元素的索引和值时,能大大简化代码的编写。

8.labmda函数:

lambda函数是一种匿名函数,可以用于创建简单的函数对象,通常用于高阶函数的参数。

基本语法
lambda arguments: expression
  • lambda:这是定义 lambda 函数的关键字。
  • arguments:表示函数的参数,可以是零个或多个参数,多个参数之间用逗号分隔。
  • expression:是一个表达式,该表达式的计算结果就是函数的返回值。lambda 函数只能包含一个表达式,不能包含复杂的语句,如 iffor 等。
特点
  1. 简洁性lambda 函数的定义通常很简短,适合用于编写简单的函数逻辑,能让代码更加简洁。
  2. 匿名性:它没有像普通函数那样的显式名称,通常作为参数传递给其他高阶函数使用,使用完后不会在命名空间中保留函数名。
  3. 一次性使用:由于其简洁性和匿名性,lambda 函数常用于临时需要一个小函数的场景,用完即弃。

numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers)
对比总结
  • 语法复杂度:普通函数需要使用 def 关键字、函数名、参数列表、冒号、缩进等,语法相对复杂;而 lambda 函数语法简洁,一行即可定义。
  • 功能复杂性:普通函数可以包含复杂的语句和逻辑,如 if 语句、for 循环等;lambda 函数只能包含一个表达式,功能相对简单。
  • 命名和复用性:普通函数有明确的名称,可以在代码中多次调用,具有较高的复用性;lambda 函数通常是匿名的,主要用于一次性的简单操作。
注意事项
  • 表达式限制lambda 函数只能包含一个表达式,不能包含语句。如果需要实现复杂的逻辑,建议使用普通函数。
  • 可读性:虽然 lambda 函数简洁,但如果表达式过于复杂,会降低代码的可读性。在这种情况下,使用普通函数可能更好。

综上所述,lambda 函数是 Python 中一种非常有用的工具,在需要简单函数逻辑且不需要复用的场景下,能让代码更加简洁高效。

                                              好啦Python中的高阶函数就讲到这里拉


http://www.kler.cn/a/540656.html

相关文章:

  • 今日AI和商界事件(2025-02-10)
  • 前端页面添加水印
  • 【大模型】DeepSeek-V3技术报告总结
  • 2 CXX-Qt #[cxx_qt::bridge] 宏指南
  • SQL自学,mysql从入门到精通 --- 第 14天,主键、外键的使用
  • 网络协议课程笔记上
  • 主机安全:数字时代的基石
  • harmonyOS的路由跳转及数据请求
  • UNet-二维全景X射线图像牙齿分割(代码和模型修改)
  • DeepSeek神经网络:技术架构与实现原理探析
  • Harmony os router 使用详解
  • 基于UVM搭验证环境
  • 代码随想录_二叉树
  • 【多模态大模型】系列4:目标检测(ViLD、GLIP)
  • 因果推断与机器学习—特定领域的机器学习
  • 如何在 CSS Modules 中使用 Sass 或 Less?
  • stm32 deinit 函数作用
  • 华硕笔记本怎么一键恢复出厂系统_华硕笔记本一键恢复出厂系统教程
  • 探索 Amazon Aurora DSQL:基本操作全解析(系列①)
  • 萌新学 Python 之 If 语句
  • Vue 响应式渲染 - 过滤应用
  • layui怎么请求数据
  • NFTScan | 02.03~02.09 NFT 市场热点汇总
  • 操作系统—文件管理
  • 【含文档+PPT+源码】基于微信小程序的社交摄影约拍平台的设计与实现
  • Vue的Diff算法与React的Diff算法有何不同?