什么是高阶函数?把函数作为参数传入或把函数做为结果值返回,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。函数式编程的特点:
- 函数本身可以赋值给变量,赋值后变量为函数;
- 允许将函数本身作为参数传入另一个函数;
- 允许返回一个函数。
在前面的章节中,我们知道可以用abs()这个函数来得到一个数的绝对值,如:
print('abs(-100):', abs(-100))
以上代码,输出:
abs(-100): 100
如果,我们把代码修改下,把abs赋值给一个变量:
f = abs print(f(-100))
以上代码,输出:
100
可见,abs(-100)是函数调用,而abs是函数本身,要获得函数调用结果,我们可以把结果赋值给变量。函数本身也可以赋值给变量,即:变量可以指向函数,这时变量就获得了函数的功能,如上例中的 f ,直接调用f()和直接调用abs()完全相同。
那么函数名是什么呢?函数名其实就是指向函数的变量!对于abs()这个函数,完全可以把函数名abs看成变量,它指向一个可以计算绝对值的函数!
如果把abs指向其他对象,会有什么情况发生?
abs = 10
print(abs(-10))
把abs指向10后,就无法通过abs(-10)调用该函数了!因为abs这个变量已经不指向求绝对值函数而是指向一个整数10!当然实际代码绝对不能这么写,这里是为了说明函数名也是变量。
注:由于abs函数实际上是定义在import builtins模块中的,所以要让修改abs变量的指向在其它模块也生效,要用import builtins; builtins.abs = 10。关于什么是模块,后面会讲到,这里不要去纠结。
既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
一个最简单的高阶函数:
def add(x, y, f): return f(x) + f(y)
当我们调用add(-5, 6, abs)时,参数x,y和f分别接收-5,6和abs,根据函数定义,我们可以推导计算过程为:
x = -5 y = 6 f = abs f(x) + f(y) ==> abs(-5) + abs(6) ==> 11 return 11
用代码验证下:
def add(x, y, f): return f(x) + f(y) print(add(-5, 6, abs))
1、map函数
这是Python内置的一个函数,map()函数接收两个参数,一个是函数,一个是Iterable(迭代器对象),map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator(迭代器)返回:
def f(x): """ 返回一个数的3次方 :param x: 数 :return: 3次方后的结果 """ return x**3 r = map(f, [1, 2, 3, 4, 5]) print(list(r))
以上代码,输出:
[1, 8, 27, 64, 125]
map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
当然,不需要map()函数,写一个循环,也可以计算出结果:
def f(x): """ 返回一个数的3次方 :param x: 数 :return: 3次方后的结果 """ return x**3 L = [] for n in [1, 2, 3, 4, 5]: L.append(f(n)) print(L)
执行后,结果是一样的,但这样的写法,我们并不能直观的知道f()是作用在列表的所有元素上,并返回一个列表,我们必须读了源代码后才知道。
所以,map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x3,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:
print(list(map(str, [1, 2, 3, 4, 5])))
以上代码,输出:
['1', '2', '3', '4', '5']
当然,更多的时候我们也会配合lambda来使用,如:
r = map(lambda x: x**3, [1, 2, 3, 4, 5]) print(list(r))
以上代码,输出:
[1, 8, 27, 64, 125]
2、reduce函数
reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
对一个序列求和,就可以用reduce实现:
from functools import reduce def add(x, y): return x + y print('reduce(add, [1, 3, 5, 7, 9]) = ', reduce(add, [1, 3, 5, 7, 9]))
以上代码,输出:
reduce(add, [1, 3, 5, 7, 9]) = 25
当然求和运算可以直接用Python内建函数sum(),思考:如何把序列 [1, 2, 3, 4, 5] 转化为整型的 12345 ,下面给出代码但请尽可能自己先写出
from functools import reduce def f(x, y): return x*10 + y res = reduce(f, [1, 2, 3, 4, 5]) print(res)