定义
>>> def counter(base):
... def inc(x=1):
... nonlocal base
... base += x
... return base
... return inc
...
>>> inc = counter(3)
>>> inc(3)
6
>>> inc(3)
9
这里返回的不是一个值,是一个函数。
这种返回值是一个函数或者参数是函数的函数的情况,我们就称为高阶函数
即:
- 返回值是函数
- 参数是函数
这两种情况的函数,就叫做高阶函数。
在python中,一切皆对象,变量是对象,函数也是对象,并且它可以和普通对象一样赋值,作为参数,作为返回值。
>>> def fn():
... print('fn called')
...
>>> f = fn()
fn called
说明函数可以赋值,当我们函数作为返回值是,就称为高阶函数。
高阶函数的作用
定义一个函数sort,传入一个可迭代对象:
>>> def sort(it):
... ret = []
... for x in it:
... for i, e in enumerate(ret):
... if x > e:
... ret.insert(i, x)
... break
... # 如果最后还没有break,就进入else
... else:
... ret.append(x)
... return ret
...
>>> sort([1,3,5,23,2,4])
[23, 5, 4, 3, 2, 1]
如上将大于改成小于就可以得到从小到大的排列顺序。另外也可以多加一个判断的形式来实现顺序的变换。如下:
def sort(it, r=False):
ret = []
for x in it:
for i, e in enumerate(ret):
if r:
if x < e:
ret.insert(i, x)
break
else:
if x > e:
ret.insert(i, x)
break
else:
ret.append(x)
return ret
这个函数采用了默认参数,默认是顺序排列的。但是这样会有点繁琐,下面是优化版:
def sort(it, r=False):
ret = []
def cmp(a, b):
if r:
return a < b
else:
return a > b
for x in it:
for i, e in enumerate(ret):
if cmp(x, e):
ret.insert(i, x)
break
else:
ret.append(x)
return ret
将顺序的比较抽出来写成了cmp函数,然后原来的if判断直接采用了函数判断的形式。
将cmp函数移到外面也是可以的:
def cmp(a, b):
return a < b
def sort(it):
ret = []
for x in it:
for i, e in enumerate(ret):
if cmp(x, e):
ret.insert(i, x)
break
else:
ret.append(x)
return ret
这里可以将cmp作为一个函数传入。也可以改成匿名函数的形式:
def sort(it, cmp=lambda a,b: a<b):
ret = []
for x in it:
for i, e in enumerate(ret):
if cmp(x, e):
ret.insert(i, x)
break
else:
ret.append(x)
return ret
小结
函数作为返回值:通常是用于闭包的场景,需要封装一些变量
封装:将我有的一些值放起来,不被人看到与使用,将其锁起来。
函数作为参数:通常用于大多数逻辑固定,少部分逻辑不固定的场景