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