Python高阶函数
高阶函数(经常简称为HOFs)就是以一个或多个函数为参考并返回一个函数的函数。
>>>x=abs(-10)
这样是我们常见的方式,把函数的调用结果,赋值给变量
其实python还可以支持把函数赋值给变量
>>>f=abs
>>>f(-10)
说明变量f指向了abs函数本身,直接调用abs()函数和调用f()一样
那么什么是高阶函数呢:
def add(a,b,f)
return f(a)+f(b)
即把一个函数作为参数,这种函数称为高阶函数,我们可以想一下,函数的参数一般意义上来说,应该是变量。但是函数又能赋值给变量,因此函数也就可以作为参数调用。
a=”abc”
b=”efg”
f=upper
return f(a)+f(b) 等价于 upper(“abc”)+upper(“efg”) 等价于 “ABCEFG”
python中一些有用的高阶函数包含在functools中,而另一些则是内建的。
通常认为map(),filter()以及functools.reduce()是python中高阶函数的基础模块。
内建函数map()与filter()与解析式(comprehension)等价(尤其是考虑到目前生成器解析式(generator comprehension)已经可用),但是很多python程序员认为解析式可读性更强一些。例如,以下表达式是等价的:
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
>>>list(map(str,[1,2,3,4,5,6,7,8,9]))
[‘1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’]
函数functools.reduce()非常通用,强大但是想发挥其全部威力的技巧却相当微妙。它以前后相继的迭代器对象为参数,并以某种方式将它们结合起来。reduce()最常见的用法可能已经由内建函数sum()涵盖了,sum()函数实际上只是以下形式的简写:
reduce把一个函数作用在一个序列[x1,x2,x3…]上,让这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累计计算,其效果就是:
reduce(f,[x1,x2,x3,x4])=f(f(f(x1,x2),x3),x4)
因此上述表达式就十分好理解了。
现在引入一个概念lambda函数:
如果我们要做两个数的加和,一般的写法为
def sum(x,y):
return x+y
如果我们用lambda来实现:
p=lambda x,y:x+y
print(p(4,6))
匿名函数lambda:是指一类无需定义函数名的函数或子程序
lambda函数可以接收任意多个参数(包含可选参数)并且返回单个表达式的值
注意:lambda函数不能包含命令,包含的表达式不能超过一个
那么,我们还可以用lambda函数来进一步简化操作:
reduce(lambda x,y : x*10+y , [100,99,98,97])
reduce第一个函数表达式,必须接收2个参数。
其次reduce还可以接收一个缺省的初始化值,比如:
f= lambda x,y :x+y
reduce(f, [1, 3, 5, 7, 9], 100)
正常的计算逻辑是:
先计算头两个元素:f(1, 3),结果为4;
再把结果和第3个元素计算:f(4, 5),结果为9;
再把结果和第4个元素计算:f(9, 7),结果为16;
再把结果和第5个元素计算:f(16, 9),结果为25;
由于没有更多的元素了,计算结束,返回结果25。
但是有一个初始化的值,那在最开始的一步计算就应该为f(100,1)
因此最后的答案应该为125。
>>> add5 = lambda n: n+5
>>> reduce(lambda l,x: l+[add5(x)],range(10),[])
[5,6,7,8,9,10,11,12,13,14]
>>> # simpler: map(add5,range(10)
>>> isOdd = lambda n: n%2
>>> reduce(lambda l,x: l+[x]if isOdd(x) else l, range(10),[])
[1,3,5,7,9]
>>> # simpler: filter(isOdd,range(10))
这个就比较好理解了,一个空数据,加上一个只有一个5元素的数组,就会形成一个5的数组,依次增加,为什么说reduce强大,reduce可以替代map及filter函数。
这些reduce()表达式令人困惑,但是它们说明了这个函数具有多么强大的通用性:任何对前后相继元素的计算都可以表达为reduce()的形式。
而filter就是指对参数进行过滤
和map()类似,filter()也接收一个函数和一个序列。与map()不同的是,filter()把函数作用在每个元素后,根据返回的布尔类型,决定是保留还是舍弃元素。
例如:
filter(lambda n : n%2==1,range(10))
也有一些常用的高阶函数不包含在python的原始库中,但是它们可以通常容易编写 (并且有些第三方库包含了这些函数)。不用的库以及不同的语言可能使用不同的函数名称,但是它们都拥有类似的功能。在具体的使用过程中,可以详细去研究。