python闭包

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python闭包相关的知识,希望对你有一定的参考价值。

声明 :初学python,此文主要作为笔记,知识面浅,若理解有误请多担待,指出错误更是感激不尽!

闭包 :当函数存在嵌套,并且子函数引用了父函数中的变量,可以访问这些变量的作用域就形成闭包。如果子函数没有访问父函数中的变量,就不存在闭包,闭包每次运行是能够记住引用的外部作用域的变量的值。形象点说就是有一个大盒子,里面有个小盒子,小盒子里面用到的一些东西是来自外部的大盒子的,那么这些来自大盒子的东西,就是闭包。

接下来全部使用例子来解释闭包!

例子 一

#这里定义的是一个求和函数

def lazy_sum(*args):
    def sum(): #我就是闭包!因为我引用了外部函数lazy_sum的局部变量args
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum #注意这里返回的是一个函数,返回函数(闭包)的特点看下面的例子
f = lazy_sum(1,2,3)
print(f())

#输出 6

可能应该略微知道闭包是个啥东西了,但是小心!返回的函数是没有马上执行的!直到被调用了才执行,所以这里有坑!什么坑呢?看例子!如果理解了下面的例子,那么你对闭包的理解和使用就更进一步了!

例子 二

#下面代码输出并非1、4、9而是9、9、9

def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i #先把局部变量i存起来,但是并没有马上执行
        fs.append(f)
    return fs
f1, f2, f3 = count() #等到执行的时候局部变量已经是3,所以说
                             #打印出来的结果不是1、4、9而是9、9、9!
print(f1())
print(f2())
print(f3())

#因此返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

#那硬是要使用循环变量怎么办?既然i属于外部函数,那么我们只要定义一个内部函数暂存下外部函数的值即可,代码如下

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

接下里再通过一个例子看看返回闭包的又一特点

例子 三

#猜猜下面代码会输出什么?复制代码在你的IDE上印证以下吧!

def fun():
    x = 5
    def inner(): #没错!俺是闭包!
        nonlocal x
        x += 1
        return x
    return inner #还是将闭包返回出去
small_box = fun()
for i in range(1, 4):
    print(small_box())

#不知你猜对没有,这里就是返回闭包的一个强大功能了,因为返回的是
#闭包,所以相当于每一次都把inner()执行一遍,而非重新执行fun(),
#相当于将大盒子里面的小盒子取出来,然后不断执行小盒子里面的操作,
#而小盒子里面拥有的大盒子的东西会一直改变,所以输出并非三个6!

最后咱们结合第二和第三个例子构造第四个例子作为练习猜猜输出

例子 四

#猜猜下面这两段代码输出啥?
def foo():
    ret = []
    x = 5
    for i in range(1, 4):
        def inner():
            nonlocal x
            return x
        x += 1
        ret.append(inner)
    return ret
L = foo()
for fun in L:
    print(fun())

#----------华丽分割--------------

def foo():
    ret = []
    x = 5
    for i in range(1, 4):
        def inner():
            nonlocal x
            x += 1
            return x
        ret.append(inner)
    return ret
L = foo()
for fun in L:
    print(fun())

#试着自己解释下原因

 

欢迎指出错误的地方,以后学到相关的还会继续补充!

 

以上是关于python闭包的主要内容,如果未能解决你的问题,请参考以下文章

Python进阶闭包(Closure)

python闲谈--闭包

python中对 函数 闭包 的理解

Python深入04 闭包

理解Python中的闭包

python闭包