闭包迷思

起因于慕课上的一段代码:

# 希望一次返回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)

闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。

因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量。

你可能感兴趣的:(闭包迷思)