python 闭包

谈起闭包想必大家或多或少都有些头大吧。

什么是闭包:

闭包就是在一个外函数定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了闭包。

我们看一个小小的例子:

def outer(a):       #外函数
    b = 10 
    def inner():    #内函数
        print(a+b)  #在内函数中用到了外函数的临时变量
    return inner    #外函数的返回值是内函数的引用

demo = outer(6)     #demo存了外函数的返回值,也就是inner的引用,相当于执行inner函数
demo()   #16

demo2 = outer(10)
demo()   #20

#外函数结束时发现内部函数将会调用自己的临时变量,这两个临时变量就不会被释放。但是只能引用不能改变a,b的值

上面这个例子就是一个很简单却又很典型的闭包函数。

使用闭包时内部不能修改外部函数的局部变量:在上代码吧

def outer():
    m = 1
    def inner():
        m = 0
        print(m)
    print(m)
    inner()
    print(m)
    return inner
result = outer()
result()

1
0
1
0
#我么发现m的值不是所谓的 1 0 0 0而是 1 0 1 0所以inner函数不能改变外部函数的值。

这个例子就是形象的说明 那么在列举在python闭包中经典的错误例子

def outer():
    a = 6
    def inner():
        a = a+1
    return inner

result = outer()
result()

#将会报错如下:
UnboundLocalError: local variable 'a' referenced before assignment

错误的原因是啥呢?

在闭包inner()函数中,变量a在赋值符号‘=’的左面,被python认为是inner()函数的局部变量,python会在右边找到赋值给a的值,但是没有找到所以报错。那外不函数有a啊为啥a没有值,应为刚才说了内部不能改变外部函数的值,只能引用外部函数的变量。

那么又有问题了,内部函数怎么改变外部函数变量的值呢?

在python2中用到的方法是:把闭包变量改变成可变类型的数据类型,比如列表

def outer(a):
    c = [a]   #将c变为可变类型列表
    def inner():
        c[0] +=1   #可以改变c的值
        print(c[0])
    return inner

result = outer(6)
result()

结果为7 

pyhton3中又添加了一种的方式:nonlocal关键字声明一个变量,表明这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量来在看代码!!!

def outer(a):
    b = a
    def inner():
        nonlocal b  nonlocal关键之向上一层变量中找变量b
        b+=1
        print(a+b)
    return inner
demo = outer(5)
demo

#结果是11

以上介绍了内部函数如何改变外部函数的变量值的两种方法:

  • 把闭包变量改变成可变类型的数据类型(如列表)
  • 在内部函数中加入关键子nonlocal

最高要注意一点的是:在闭包过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,但是都在使用同一份闭包变量看看代码吧

def outer(a):
    def inner(b):
        nonlocal a
        a+=b
        ptint(a)
    return inner

a = outer(3)
a(4)
a(4)

#结果为
7
11

两次打印的值不同,所以可以知道每次调用inner的时候,使用的闭包变量实际上是同一个。

总结:闭包要满足的条件

  1. 必须有嵌套函数
  2. 内部函数引用外部变量
  3. 外部函数返回这个内部函数

那就这样吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值