聊聊Python闭包(Closure)的那点事。

作者:J.sky · 发表于:
2017-10-09T15:36:19.000000Z
· 更新于:
2023-08-13T22:54:33.234776Z
· Tag: Python基础

记得当年学JavaScript时,对闭包的认识那真是朦朦胧胧,后来接触到jQuery之后,对闭包的认识还是一知半解,可能被之前一直学习本分的静态语言java给耽误了。。。。。。好吧,闭包到是个什么?是一个让初学编程的人头疼的问题

Pythib闭包

先来一个栗子,我们慢慢理顺一下:

def callf():
    def hello():
        return "hello world"
    return hello

cf = callf() #创建一个callf函数,这时把hello()赋值给了cf
print(type(cf)) # 查看cf类型,证实上边的结论。
print(cf()) #打印最终结果。

在一个函数中,把这个函数内部的一个函数做为返回值,那个这个被返回的函数就可以叫做闭包。(这条是本人自己写的,和网上其它处的理论会有些出入或是不同) 上边就算是闭包最简单的例子,多看几次应该就理解了。

再看下边的例子,这是一个利用闭包设计的简单自减计数器,其实我第一眼看去的时候就觉得为什么要这么写?

def countdown(n):
    def next():
        nonlocal n 
        r = n 
        n -= 1
        return r
    return next

nt = countdown(5)
while True:
    v = nt()
    print(v)
    if not v :break

这个自减计数器的应该还有几种其它写法,而且加之使用nonlocal这个关键字,使人更加迷惑了,如果注释掉nonlocal n,程序运行就会抛出错误,可见nonlocal的使用使next()函数内部变量n的值可以修改。 本人对此得的理解也不是很好,希望有大侠给与指点,也许这个例子不太理想。

再看循环中的闭包:

def loop():
    fs = []
    for i in range(1,4):
        def f():
            return i*i
        fs.append(f)
    return fs
f1,f2,f3 = loop()
print(f1())

f1()的打印竟然9,这个有点出乎意料!我们修改一下这个函数

def loop(): 
    def f(j):
        return lambda: j*j
    fs = []
    for i in range(1,4):
        fs.append(f(i))       
    return fs
f1,f2,f3 = loop()
print(f1())
print(f2())
print(f3())

对比上边的两段代码,第一段直接返回了三次循环的最终结果,而第二段代码,再循环中遇到了f()函数return所以暂停了程序的运行,直到第二个赋值时又循环了一次,然后继续,这也说明,闭包的函数不要放在循环体内,不然直接返回的是循环的最终结果。 有的同学会问,了解闭包有什么用?闭包是装饰器和生成器的基础,如果你应用Python函数的高级应用,不妨仔细的了解一下闭包吧。

参考文档

本文源码下载: