高阶函数
接受函数为参数,或者把函数作为结果返回的函数是高阶函数(high-order function)。map函数就是一个,内置函数sorted也是:可选的key参数用于提供一个函数,它会应用到各个元素上进行排序
# 根据单词长度给一个列表排序
fruits = ['strawbery', 'fig', 'apple', 'cherry', 'respberry', 'banana']
sorted(fruits, key=len)
['fig', 'apple', 'cherry', 'banana', 'strawbery', 'respberry']
任何单参数函数都能作为key参数的值。例如,为了创建押韵词典,可以把各个单词反过来拼写,然后排序。但是列表中的单词没有变,只是把反向拼写当作排序条件,因此berry都排在一起
# 根据反向拼写给一个单词列表排序
def reverse(word):
return word[::-1]
reverse('testing')
'gnitset'
sorted(fruits, key=reverse)
['banana', 'apple', 'fig', 'strawbery', 'respberry', 'cherry']
在函数式编程范式中,最为人熟知的高阶函数有map、filter、reduce和apply。apply函数在Python3中移除了,因为不再需要它了。如果想使用不定量的参数调用函数,可以编写fn(*args,**keywords),不用再编写apply(fn,args,kwargs)
map、filter和reduce的现代替代品
函数式语言通常会提供map、filter和reduce三个高阶函数(有时使用不同的名称)。在Python中,map和filter还是内置函数,但是由于引入了列表推导和生成器表达式,它们变得没那么重要了。列表推导或生成器表达式具有map和filter两个函数的功能,而且更易于阅读
# 计算阶乘列表:map和filter与列表推导比较
def factorial(n):
return 1 if n < 2 else n * factorial(n - 1)
fact = factorial
list(map(fact, range(6))) # 构建0!到5!的一个阶乘列表
[1, 1, 2, 6, 24, 120]
[fact(n) for n in range(6)] # 使用列表推导式执行相同的操作
[1, 1, 2, 6, 24, 120]
list(map(fact, filter(lambda n: n % 2, range(6)))) # 使用map和filter计算直到5!的奇数阶乘列表。
[fact(n) for n in range(6) if n % 2] # 使用列表推导做相同的工作,换掉map和filter,并避免了使用lambda表达式
[1, 6, 120]
在Python3中,map和filter返回生成器(一种迭代器),因此现在它们的直接替代品是生成器表达式(在Python2中,这两个函数返回列表,因此最接近的替代品是列表推导)
在Python2中,reduce是内置函数,但是在Python3中放到functools模块里。这个函数最常用于求和,自2003年发布的Python2.3开始,最好使用内置的sum函数。在可读性和性能方面,这是一项重大改善
# 使用reduce和sum计算0~99之和
from functools import reduce # 从Python3.0开始,reduce不再是内置函数
from operator import add # 导入add,以免创建一个专求两数之和的函数
reduce(add,range(100)) # 计算0~99之和
4950
sum(range(100)) # 使用sum做相同的求和;无需导入和创建求和函数
4950
sum和reduce的通用思想是把某个操作连续应用到序列的函数上,累计之前的结果,把一系列值规约成一个值
all和any也是内置的归约函数
all(iterable) 如果iterable的每个元素都是真值,返回True;all([])返回True
any(iterable) 只要iterable中有元素是真值,就返回True;any([])返回False