一:返回函数
1 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
2
1 def lazy_sum(*args): 2 3 def sum(): 4 ax = 0 5 for n in args: 6 ax = ax + n 7 return ax 8 return sum
a 当我们调用lazy_sum()
时,返回的并不是求和结果,而是求和函数:
>>> f = lazy_sum(1, 3, 5, 7, 9)
再调用f()返回求和结果。
b 我们在函数lazy_sum
中又定义了函数sum
,并且,内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中。这种结构称之为'闭包’。
c 当我们调用lazy_sum()
时,每次调用都会返回一个新的函数,即使传入相同的参数:
1 >>> f1 = lazy_sum(1, 3, 5, 7, 9) 2 >>> f2 = lazy_sum(1, 3, 5, 7, 9) 3 >>> f1==f2 4 False
3 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变
eg:
1 def count(): 2 def f(j): 3 def g(): 4 return j*j 5 return g 6 fs = [] 7 for i in range(1, 4): 8 fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f() 9 return fs
1 >>> f1, f2, f3 = count() 2 >>> f1() 3 1 4 >>> f2() 5 4 6 >>> f3() 7 9
4 一个函数可以返回一个计算结果,也可以返回一个函数。返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。
5 利用闭包返回一个计数器函数,每次调用它返回递增整数:
法一:创造一个生成器
1 def createCounter(): 2 def f(): 3 n=0 4 while True: 5 n=n+1 6 yield n #先创造一个生成器 7 sun=f() 8 def counter(): 9 return next(sun) #用一个函数来调用生成器 10 return counter
法二:使用列表(因为列表list是全局变量)
def createCounter(): fs = [0] #创建一个只有一个元素的列表 def counter(): fs[0] = fs[0] + 1 return fs[0] return counter
法三:使用nonlocal关键字,将局部变量变成全局变量
def createCounter(): n=0 def f(): nonlocal n n=n+1 return n return f
二:匿名函数(当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。)
lambda 参数(是可变参数):表达式。无须返回函数
a 匿名函数有个限制,就是只能有一个表达式,不用写return
,返回值就是该表达式的结果。
b 匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:
1 >>> f = lambda x: x * x 2 >>> f 3 <function <lambda> at 0x101c6ef28> 4 >>> f(5) 5 25
c 匿名函数作为返回值返回。
1 def build(x, y): 2 return lambda: x * x + y * y