高阶函数
高阶函数:一个函数可以接收另一个函数作为参数 或 一个函数可以返回一个函数作为返回值,这种函数称之为高阶函数。
#函数 add 接收 f 函数作为参数
>>> def add(x,y,f):
... return f(x)+f(y)
...
>>> add(-5,6,abs)
11
可以把匿名函数作为返回值返回
#把匿名函数作为返回值返回
def build(x, y):
return lambda: x * x + y * y
匿名函数
关键字 lambda 表示匿名函数,冒号前面的 x 表示函数参数
>>> list(map(lambda x:x*x,list(range(1,10))))
[1, 4, 9, 16, 25, 36, 49, 64, 81] def f(x):
return x*x
>>> from hello import f
>>> list(map(lambda x:x*x,list(range(1,10))))
[1, 4, 9, 16, 25, 36, 49, 64, 81] #这两种方式等价,不过第一种代码量更少。
def f(x):
return x*x #等价于 lambda x:x*x
返回函数
比如我们实现一个求和函数:
def calc_sum(*args):
ans=0
for i in args:
ans+=i
return ans
但是如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?
可以不返回求和的结果,而是返回求和的函数:
def lazy_sum(*args):
def sum():
ans=0
for i in args:
ans+=i
return ans
return sum
#调用
>>> L=list(range(1,11))
>>> f=lazy_sum(*L) #返回的函数并没有立刻执行,而是直到调用了f
>>> f()
55
在这个例子中,我们在函数 lazy_sum 中又定义了函数 sum ,并且,内部函数 sum可以引用外部函数 lazy_sum 的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
当我们调用 lazy_sum() 时,每次调用都会返回一个新的函数,即使传入相同的参数:
>>> f1=lazy_sum(*L)
>>> f2=lazy_sum(*L)
>>> f1==f2
False
一个关于“闭包”的示例:
def count():
fs=[]
for i in range(1,4): #每次循环都创建了一个新的函数,然后把创建的3个函数都返回了
def f():
return i*i
fs.append(f)
return fs
#调用
>>> f1,f2,f3=count()
>>> f1()
9
>>> f2()
9
>>> f3()
9
怎么都是9 ?!
原因在于返回的函数引用了变量 i ,但它并非立刻执行。等到三个函数都返回时,它们所引用的变量 i 已经变成了 3,因此最终结果为9......
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
def count():
fs=[]
for i in range(1,4):
def f(i):
def g():
return i*i
return g
fs.append(f(i))
return fs
#调用
>>> from hello import count
>>> f1,f2,f3=count()
>>> f1()
1
>>> f2()
4
>>> f3()
9
利用 lambda 函数简化:
def count():
fs=[]
for i in range(1,4):
def f(i):
return lambda :i*i
fs.append(f(i))
return fs
练习:利用闭包返回一个计数器函数,每次调用它返回递增整数
def count_num():
f=[0]
def count():
f[0]=f[0]+1
return f[0]
return count
>>> from hello import count_num
>>> f=count_num()
>>> f()
1
>>> f()
2
>>> f()
3
>>>
高阶函数——map
map() 函数接收两个参数,一个是函数,一个是Iterable , map将闯入的函数一次作用到序列的每个元素,并把结果作为新的 Iterator 返回
用 map 实现把一个函数 f(x)=x*x ,作用在一个 list 上后的结果输出:
>>> L=range(1,11)
>>> L=list(range(1,11))
>>> r=map(lambda x:x*x,L)
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
高阶函数——reduce
reduce() 函数是接受两个参数,把一个函数最用在一个序列上,reduce 把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
用reduce 实现序列求和
>>> from functools import reduce #使用reduce函数需先import
>>> L=list(range(1,11))
>>> reduce(lambda x,y:x+y,L)
55
用reduce 实现把一个整数序列变成整数
>>> L=list(range(1,10))
>>> reduce(lambda x,y:x*10+y,L)
123456789
用reduce + map 实现str 转换为 int 的函数
>>> def char_num(c):
... digits={'':0,'':1,'':2,'':3,'':4,'':5,'':6,'':7,'':8,'':9}
... return digits[c]
...
>>> reduce(lambda x,y :x*10+y,list(map(char_num,'')))
13654
python 有内置的str 与int 互化的函数
>>> str(4515)
''
>>> int('')
5252
练习:利用map()
函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT']
,输出:['Adam', 'Lisa', 'Bart']
: