起因于慕课上的一段代码:
# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
print f1,f2,f3 >>> 9, 9, 9
要求正常实现功能,看不明白……在评论区抄了一段:
def count():
fs = []
for i in range(1, 4):
def f(m = i):
return m * m
fs.append(f)
return fs
f1, f2, f3 = count()
print f1(), f2(), f3() >>> 1, 4, 9
???
继续看评论:
问题的产生是因为函数只在执行时才去获取外层参数i,若函数定义时可以获取到i,问题便可解决。而默认参数正好可以完成定义时获取i值且运行函数时无需参数输入的功能,所以在函数f()定义中改为f(m = i),函数f返回值改为m*m即可.
好像懂了又好像没懂。
大概就是count()返回了fs,其中保存了3个没有执行过的f,分别赋予变量f1,f2,f3
在开始的那段代码中,返回3个f时i已经变成3,这时再调用就会出现f(3),f(3),f(3) = 9,9,9
而第二段代码中,每次返回f时当前的i被固定在了变量m中,因此调用时为f(1),f(2),f(3) = 1,4,9
换言之,让fs中直接保存每次循环中执行的结果也可以达到目的:
def count3():
fs = []
for i in range(1,4):
fs.append(i*i)
return fs
f1, f2, f3 = count3()
print f1, f2, f3 >>> 1, 4, 9
最后看看课程中对此的结论:
像这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。
因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量。