Python支持多种编程范式:过程式(使用基础的语句),面向对象式(使用类)和函数式。
对于函数式编程,Python提供了一整套进行函数式编程的内置工具,如map,filter,reduce。
此外,还支持嵌套作用域闭包、匿名函数lambda、生成器,函数装饰器和类装饰器。
在Python中,一切皆为对象。
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”。
a=abs
print(a(-9))
9
map
程序对列表和其他序列常常要做的一件事,就是对每个元素进行一个操作并把其结果收集起来。
如下面的例子所示,可以使用for循环来更新一个列表中所有的数字。
counters=[1,2,3,4]
updated=[]
for x in counters:
updated.append(x+10)
print(updated)
[11, 12, 13, 14]
除此之外,我们还可以用map函数来实现。
def inc(x):
return x+10
print(list(map(inc,counters)))
[11, 12, 13, 14]
map()函数接收两个参数,一个是函数,一个是Iterable。
map函数将被传入的函数作用到每个可迭代对象的每一个元素上,并把结果作为新的Iterator返回。
由于map返回的是一个可迭代对象Iterator(详见迭代器章节),Iterator是惰性序列,因此要用list调用来强制他产生所有的结果以显示。
更进一步,如果我们将函数改成lambda表达式,同样功能的代码将缩减到一行。正是由于这些高度抽象的工具存在,python才可以写出非常简洁的代码。
print(list(map(lambda x:x+10,counters)))
[11, 12, 13, 14]
我们来看一下map源码的定义。在类map定义的函数中,通过__init__函数我们可以看到map的参数类型。
以及实现了__iter__和__next__方法从而作为一个迭代器。
class map(object):
"""
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass
def __init__(self, func, *iterables): # real signature unknown; restored from __doc__
pass
def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass
def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass
filter
和map()一样,filter()也接收一个函数和一个序列。
filter函数将被传入的函数作用到每个可迭代对象的每一个元素上,如果函数对该元素返回了True值,这个元素就会被加入结果列表中。
和map一样,filter()函数返回的也是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。
def positive(x):
if x>0:
return x
print(list(filter(positive,range(-5,5))))
[1, 2, 3, 4]
前面说到filter的功能非常类似生成式带if的语法,让我们来回顾一下,
print([i for i in range(-5,5) if i>0])
[1, 2, 3, 4]
同样,我们也可以把函数定义成lambda表达式
print(list(filter(lambda x:x>0,range(-5,5))))
[1, 2, 3, 4]
python中实现一种功能的方式多样,学会如何取舍,灵活使用往往能达到事半功倍的效果。
reduce
reduce函数接收一个函数和一个序列。这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,使用前需先导入。
import functools
def add(x,y):
return x+y
print(functools.reduce(add,[1,2,3,4]))
10
reduce的定义与map/filter相比则简单许多。函数文档中有示例来解析reduce的作用。
def reduce(function, sequence, initial=None): # real signature unknown; restored from __doc__
"""
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
"""
pass
本节介绍了函数式编程的内置工具,map,filter,reduce,即函数作为另一个函数的参数。下一节将介绍函数作为返回值。