在 Python 中,高阶函数是一类非常强大且灵活的函数。它们能够接受其他函数作为参数,或者返回一个函数。本文将深入探讨 Python 中的几个常见高阶函数:map
、reduce
、filter
、sorted
,以及如何利用它们编写简洁、高效的代码。
什么是高阶函数?
高阶函数(Higher-Order Function)是指能够接收函数作为参数,或者将函数作为返回值的函数。Python 内置了多种高阶函数,它们为我们提供了编写简洁代码的能力。
lambda
表达式
在正式开始介绍高阶函数之前,我们需要简单了解一下什么是 lambda
表达式。lambda
表达式是用于创建小型匿名函数的便捷方式。它通常在需要一个临时函数的情况下使用,尤其是在高阶函数中。lambda
表达式的语法非常简洁:
lambda arguments: expression
arguments
:函数的参数,可以是多个,用逗号分隔。expression
:一个简单的表达式,该表达式的计算结果将作为返回值。
示例:
# 定义一个计算平方的 lambda 函数
square = lambda x: x ** 2
print(square(5)) # 输出: 25
在高阶函数中,lambda
表达式常用于定义临时函数,避免了单独定义函数的繁琐。
map
函数
map
函数用于将一个函数应用到一个或多个可迭代对象(如列表、元组等)的每一个元素上,并返回一个新的可迭代对象。语法如下:
map(function, iterable, ...)
function
:应用到每个元素的函数。-
iterable
:可迭代对象,可以是一个或多个。注意,这里function的参数和可迭代对象相对应,会从每一个可迭代对象中取出一个元素然后一起传入。
示例
单个可迭代对象
将列表中的每个元素平方
numbers = [1, 2, 3, 4]
squared = map(lambda x: x ** 2, numbers)
print(list(squared)) # 输出: [1, 4, 9, 16]
在这个示例中,lambda x: x ** 2
是一个匿名函数,用于将输入的数字平方。map
函数将该函数应用于 numbers
列表中的每个元素。
多个可迭代对象
将两个列表中对应的元素相加
list1 = [1, 2, 3]
list2 = [4, 5, 6]
sum_list = map(lambda x, y: x + y, list1, list2)
print(list(sum_list)) # 输出: [5, 7, 9]
在这个示例中,lambda x, y: x + y
是一个匿名函数,它接收两个输入并返回它们的和。map
函数将这个函数应用到 list1
和 list2
中的对应元素,生成一个包含元素和的新列表。
处理用户输入
从用户输入中读取数字并进行求和
numbers = map(lambda x: eval(x), input("输入一串数字,用空格分隔: ").split())
total_sum = sum(numbers)
print(f"输入数字的和是: {total_sum}")
在这个示例中,用户输入了一串用空格分隔的数字字符串。input().split()
将这些字符串分割成一个列表,map(lambda x: eval(x), ...)
将列表中的每个字符串转换为对应的数字。然后,通过 sum
函数计算这些数字的和并输出。
reduce
函数
reduce
函数用于对一个序列进行累计计算。它逐步将序列中的元素进行二元操作,最后将其归约为一个单一的值。简单的说,就是取序列第一个元素和第二个元素进行处理,得到的新元素再与下一个元素进行操作,直到处理完所有元素。
reduce
位于 functools
模块中,需要先导入。语法如下:
from functools import reduce
reduce(function, iterable[, initializer])
function
:应用于序列的二元函数。iterable
:要处理的可迭代对象。initializer
(可选):初始值。
示例
计算列表中所有元素的乘积
from functools import reduce
numbers = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, numbers)
print(product) # 输出: 24
在这个示例中,实际的处理过程是
1X2=2
2X3=6
6X4=24
考虑列表为空的情况
当列表为空时,reduce会抛出一个异常
TypeError: reduce() of empty iterable with no initial value
因为reduce
会把第一个值作为初始值,然后进行计算。所以空列表无法得到初始值,因此报错。这时就要用到initializer
参数,手动的赋予一个初始值。比如加法初始为0,乘法初始为1。
from functools import reduce
numbers = []
product = reduce(lambda x, y: x * y, numbers, 1)
print(product) # 输出: 1
filter
函数
filter
函数用于过滤序列中的元素,返回一个符合条件的新序列。语法如下:
filter(function, iterable)
function
:用于判断元素是否保留的函数,返回True
或False
。iterable
:要过滤的可迭代对象。
示例
过滤出列表中的偶数
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens)) # 输出: [2, 4, 6]
在这个示例中,lambda x: x % 2 == 0
是一个匿名函数,用于判断一个数是否为偶数。filter
函数将这个条件应用于 numbers
列表中的每个元素,保留符合条件的元素。
求素数
number = list(range(2, 100))
num = 2
while num <= 100:
number = list(filter(lambda x: x == num or x % num, number))
num += 1
print(list(number)) # 输出: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
这里只是举例说明filter的使用,这个算法效率不高。
注意
返回的是一个迭代器,传入的可迭代对象会保存在闭包中,同是因为列表是引用类型,所以如果我们在外部修改了列表,那么filter返回的迭代器也会改变。filter
在本例中,如果循环中不用list进行转换,每次循环中都重新将number赋值为一个新的迭代器,这会导致之前生成的迭代器在后续循环中无法正确遍历。
sorted
函数
sorted
函数用于对可迭代对象进行排序,并返回一个新的排序列表。sorted
函数使用了timsort
算法,是一个高效且稳定的排序算法。
语法如下:
sorted(iterable, key=None, reverse=False)
iterable
:要排序的可迭代对象。key
(可选):一个函数,用于从每个元素中提取用于排序的关键字。reverse
(可选):一个布尔值,指定排序是否为降序,默认升序。
列表的.sort()
方法也是一样的,只是不返回新的列表,而是直接修改原列表。
示例:
按照绝对值大小排序列表
numbers = [-5, 2, -1, 0, 3, -8]
sorted_numbers = sorted(numbers, key=lambda x: abs(x))
print(sorted_numbers) # 输出: [0, -1, 2, 3, -5, -8]
在这个示例中,lambda x: abs(x)
是一个匿名函数,用于返回每个元素的绝对值,sorted
函数按照这些绝对值对列表进行排序。
综合示例
结合 map
、filter
、reduce
和 sorted
,我们可以进行更复杂的操作。例如,计算一个列表中所有偶数的平方和,并按降序排列:
from functools import reduce
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers)
squared_evens = map(lambda x: x ** 2, evens)
sorted_squares = sorted(squared_evens, reverse=True)
sum_of_squares = reduce(lambda x, y: x + y, sorted_squares)
print(sorted_squares) # 输出: [36, 16, 4]
print(sum_of_squares) # 输出: 56
在这个示例中,我们首先使用 filter
过滤出偶数,然后用 map
对偶数进行平方,接着用 sorted
将这些平方结果按降序排列,最后用 reduce
求出所有平方的和。
结语
高阶函数为我们提供了一种优雅的方式来处理可迭代对象。通过合理运用 map
、reduce
、filter
和 sorted
,我们可以编写出更加简洁和高效的 Python 代码。lambda
表达式的配合使用,更是让代码显得简洁且富有表现力。