舒巨佬去河南浪去啦,真羡慕呀,趴在自习室一上午了,困困困。。。。。。但愿今儿个能完成任务吧
分享自《流畅的Python》
高阶函数
接受函数为参数,或者把函数作为结果返回的函数是高阶函数(high-order function)。map函数就是一例,此外,内置函数sorted()也是: 可选的key参数用于提供一个函数,它会应用到各个元素上排序。
例如,若想根据单词的长度排序,只需把len函数传给key参数,实例如下:
>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'banana']
>>> sorted(fruits, key=len)
['fig', 'apple', 'cherry', 'banana', 'raspberry', 'strawberry']
任何单参数函数都能作为key的参数的值。例如,为了创建押韵词典,可以把各个单词反过来拼写,然后排序。注意,以下实例中列表里的单词没有变,我们只是把反向拼写当作排序条件,因而,各种浆果(berry)都排在一起。
>>> def reverse(word):
... return word[::-1]
>>> reverse('testing')
'gnitset'
>>> sorted(fruits,key=reverse)
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']
>>> # 这个例子很令我吃惊呀,我一直以为key=reverse是它的可选参数之一呢,原来是传递了函数对象
在函数式编程范式中,最为人熟知的高阶函数有map、filter、reduce和apply。apply函数在python2.3中标记为过时,在Python3已经移除了,因为不再需要它了。如果想使用不定量的参数调用函数,可以编写fn(*args, **keywords),不用再编写apply(fn, args, kwargs)。(P.S. 这些Python的陈年旧事我也是第一次听说)
map、filter和reduce这三个高阶函数还能看到,不过多数使用场景下都有更好的替代品。
map、filter和reduce函数的现代替代品
函数式语言通常会提供map、filter和reduce三个高阶函数(有时使用不同名称)。在Python3中map和filter是内置函数,但由于引入列表推导和生成器表达式他们便没那么重要了。列表推导或是生成器表达式具有map和filter两个函数的功能,而且更易于阅读,示例如下:
(这是接下来用到的函数fact,我的上篇日记中有写)
>>> def factorial(n): # 这是一个控制台会话,因此在“运行时”创建一个函数
... '''return 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]
>>> # 使用map和filter计算知道5!的奇数阶乘列表
>>> list(map(fctorial, filter(lambda n:n%2, range(6))))
[1, 6, 120]
>>> # 使用列表推导做相同的工作,换掉map和filter,避免使用lambda表达式
>>> [factorial(n) for n in range(6) if n % 2]
在python3中,map和filter 返回生成器(一种迭代器),因而现在它们的直接替代品是生成器表达式(Python2中,这两个函数返回列表,因此最接近的替代品是列表推导)。
在python2中,reduce是内置函数,但在Python2.3开始,最好使用内置的sum函数,在可读性和性能方面,这是一项重大改善!示例如下:
>>> 致敬高斯,哈哈!
>>> from functools import reduce # Python3起,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
为了使用高阶函数,有时创建一次性的小型函数更加便利,这边是匿名函数存在的原因——明儿的日记!