函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
一、高阶函数
1.函数可以赋值给变量,即变量指向函数本身(不是函数名,因为函数名也只是一个指向函数本身的变量)。通过该变量可以调用函数。
(1)
print(abs(-9)) #输出9
print(abs) #输出函数本身
f = abs #将变量f指向函数
print(f(-19)) #通过变量调用函数
(2)
函数名其实就是指向函数的变量!对于abs()这个函数,完全可以把函数名abs看成变量,它指向一个可以计算绝对值的函数!abs=10,给变量abs赋值后,再调用abs()就会失败。
2.传入函数:就是将函数名a作为参数传入到函数b中,在b中调用a。这样设计的意义是啥?
3.map/reduce:
(1)
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
>>> def f(x):
... return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
你可能会想,不需要map()函数,写一个循环,也可以计算出结果:
L = []
for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
L.append(f(n))
print(L)
的确可以,但是,从上面的循环代码,能一眼看明白“把f(x)作用在list的每一个元素并把结果生成一个新的list”吗?(这就是设计高阶函数的意义吧)。所以,map()作为高阶函数,事实上它把运算规则抽象了,
(2)
再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
以下是利用map、reduce将字符串转化为数字的方法:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> def char2num(s):
... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
首先,通过map将char2num 作用在字符串 ‘13579’(Iterable)上,返回一个新的Iterator。然后,通过reduce将fu作用在这个Iterator(序列)上。
4.filter:
和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
(参考:点击打开链接)
5.sorted:
Python内置的sorted()函数就可以对list进行排序:
>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]
此外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
['about', 'bob', 'Credit', 'Zoo']
二、返回函数
三、匿名函数
四、装饰器
五、偏函数
(用到时再理解吧)