一等函数
在 Python 中,函数是一等对象。一等对象需要具备以下几个条件:
1.在运行时创建
2.能赋值给变量或者数据结构中的元素
3.能作为参数传递给函数
4.能作为函数的返回值
在 Python 中,整数、字符串、字典以及所有的函数都是一等对象,接下来我们来看把函数作为对象的实际应用。
把函数视作对象
首先我们通过一个简单的示例来说明函数为什么是对象。
>>> def myFunc(n):... '''return n!'''
... return n*n
...
>>> myFunc(5)
25
>>> myFunc.__doc__
'return n!'
>>> type(myFunc)
<class 'function'>
>>>
首先,我们直接在控制台创建一个函数。
然后通过函数调用__doc__属性,而__doc__就是函数对象中众多属性的其中一个。
然后通过 type(myFunc)查看函数类型,它是 function 类的一个实例。
由以上示例可以看出函数其实就是一个对象。
OK,接下来再通过一个示例来展示函数对象的”一等“本性。
>>> fun = myFunc>>> fun
<function myFunc at 0x1015a2268>
>>> fun(5)
25
>>> map(fun,range(5))
<map object at 0x10177a550>
>>> list(map(fun,range(5)))
[0, 1, 4, 9, 16]
>>>
这个示例中,通过别的名称使用函数,再把函数作为参数传递。
我们把 myFunc函数赋值给变量 fun,然后通过变量名来调用,还能把它当做参数传递给 map 函数,map 函数返回一个可迭代的对象,里面的元素是把第一个参数(一个函数)应用到第二个参数(一个可迭代对象,这里是 range(5))中各个元素上得到结果。
有了一等函数,就可以使用函数式风格编程了。函数式编程的特点之是使用高阶函数。
高阶函数
高阶函数的定义:接收函数为参数,或者把函数作为结果返回的函数。
比如 map函数就是一个高阶函数。另外,内置函数 sorted 也是,可选的 key 参数用于提供一个函数,它会应用到各个元素上进行排序。
来看一下 sorted 函数的简单示例:
>>> fruits = ['strawberry','fig','apple','cherry']>>> sorted(fruits,key = len)
['fig', 'apple', 'cherry', 'strawberry']
>>>
任何单参数函数都能作为 key 参数的值。
在看个示例,为了创建押韵词典,可以把各个单词反过来拼写,然后进行排序。
示例:根据反向拼写给一个单词列表进行排序
>>> fruits = ['strawberry','fig','apple','cherry','raspberry']>>> def reverse(word):
... return word[::-1]
...
>>> reverse('testing')
'gnitset'
>>> sorted(fruits,key=reverse)
['apple', 'fig', 'raspberry', 'strawberry', 'cherry']
>>>
注意,以上示例中列表的单词并没有变,只是把反向拼写当做排序条件。
在函数式编程中,最熟知的高阶函数有 map、filter、reduce,不过多数使用场景下都有更好的替代品。
map、filter与reduce的现代替代品
函数式编程通常会提供map、filter与reduce三个高阶函数,在 Python3中,map 和 filter 还是内置函数,但是由于引入了列表推导和生成器表达式,它们变得不那么重要了。可以使用列表推导或生成器表达式完全具有可以用来替代这两个函数,并且更易于阅读。
接下来看看如何用列表式推导来替代 map 和 filter
>>> list(map(fun,range(6)))[0, 1, 4, 9, 16, 25]
>>> [fun(n) for n in range(6)]
[0, 1, 4, 9, 16, 25]
>>> list(map(fun,filter(lambda n:n%2,range(6))))
[1, 9, 25]
>>> [fun(n) for n in range(6) if n%2]
[1, 9, 25]
>>>
Python3中,map 和 filter 返回生成器(一种迭代器),因此现在它们的直接替代品是生成器表达式。filter 的作用是用于过滤列表,上面使用量 Lambda 表达式,其可阅读性相对来说没有列表推导的高。
接下来看看 reduce,在 Python2中,reduce 是内置函数,但是在 Python3中放到 functools 模块中了,这个函数最常用于求和,但是从 Python2.3起,求和函数可以使用内置的 sum 函数,在可读性和性能方面,有了很大的改善。
示例:使用 reduce 和sum 计算和
>>> from functools import reduce>>> from operator import add
>>> reduce(add,range(100))
4950
>>> sum(range(100))
4950
>>>
以上可以看到,使用 reduce 求和需要导入和创建求和函数,但是使用 sum 就不用,非常简单。
sum 和 reduce 的通用思想是把某个操作连续应用到序列的元素上,并累计之前的结果,把一系列值归约成一个值。
此外,all 和 any 也是内置的归约函数。
1.all(iterable)
如果iterable的每个元素都是真值,返回 True,all([])返回 True
2.any(iterable)
如果iterable中有元素是真值,就返回 True,any([])返回 False
本文参考:《流畅的 Python》.
《流畅的 Python》电子书高清中文版下载地址,在这里