1、返回函数
Python中除了返回函数值之外,还可以返回函数,就像前面说的,函数也可以看做一个变量,那么返回函数的意义在于什么呢?——延缓函数的调用,有什么应用场景暂且还不知道,后续理解补充。总之,可以想调用该返回的函数的时候再调用。
用慕课网上廖老师的例子说明一下:
def f():
print ('call f()...')
def g():
print('call g()...')
return g
>>> x=f()call f()...
>>> x()
call g()...
>>> x
<function f.<locals>.g at 0x0000000003E157B8>
eg:延缓调用求积函数
import functools from reduce
def calc_prod(lst):
def lazy_prod(lst):
def prod(x, y):
return x * y
return reduce(prod, lst)
return lazy_prod
2、闭包
闭包也就是内部定义的函数引用了外部定义的变量,且返回内部函数;内部定义的函数无法在外面访问。定义闭包,目的可以防止一些函数被外部代码调用。
摘抄老师的一句话:闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。
eg:计算1*1 ,2*2, 3*3的结果
错误的例子是:
def func(): print('call func()....') fs = [] for i in range(1, 4): def mul_i(): print('call mul_i()...') print ('%d * %d = %d'%(i, i, i*i)) return i*i fs.append(mul_i) return fs
>>> f1,f2,f3=func()
call func()....
i = 1
i = 2
i = 3
>>> f1()
call mul_i()...
3 * 3 = 9
9
>>> f2()
call mul_i()...
3 * 3 = 9
9
>>> f3()
call mul_i()...
3 * 3 = 9
9
当func返回3个函数的时候,结果没有一个一个立刻执行,而是等3个函数的返回结果都出来的时候才执行,这3个函数所引用的变量都变成了3。类似于返回地址还是返回值的问题
因此,廖老师给出建议——返回函数不要引用任何循环变量,或者后续会发生变化的变量。
那么如果要是用闭包,那么如何改写函数呢?方法就是,定义一个变量,该变量不引用外部的变量。在需要使用时就把它计算出来
def func(): fs = [] print('call func()....') for i in range(1, 4): def mul_i(m = i): print('m = %d, i = %d' %(m,i)) print('call mul_i()....') print ('%d * %d = %d'%(m, m, m*m)) return m*m fs.append(mul_i) return fs
>>> f1,f2,f3=func()
call func()....
>>> f1()
m = 1, i = 3
call mul_i()....
1 * 1 = 1
1
>>> f2()
m = 2, i = 3
call mul_i()....
2 * 2 = 4
4
>>> f3()
m = 3, i = 3
call mul_i()....
3 * 3 = 9
9
-----------
看到另一个方法,这里补充:
def func(): fs = [] print('call func()....') for i in range(1, 4): def mul_i(): print('call mul_i()....') print ('%d * %d = %d'%(i, i, i*i)) return i*i fs.append(mul_i()) return fs
>>> f1,f2,f3=func()
call func()....
call mul_i()....
1 * 1 = 1
call mul_i()....
2 * 2 = 4
call mul_i()....
3 * 3 = 9
方法二理解为立刻返回结果,而方法一理解为延缓返回结果。方法二已经不是一个闭包了。
方法二中返回的函数立刻执行了
---------------------
廖老师给出的方法是再定义一个函数
def func(): print('call func()...') fs = [] for i in range(1, 4): def f(x): print('call f()...') print('x = %d' %x) def g(): print('call g()...') print('x = %d' %x) return x*x return g r = f(i) fs.append(r) return fs>>> f1,f2,f3=func()
call func()...
call f()...
x = 1
call f()...
x = 2
call f()...
x = 3
>>> f1()
call g()...
x = 1
1
>>> f2()
call g()...
x = 2
4
>>> f3()
call g()...
x = 3
9