python快速学习系列(4):闭包

闭包概述:
-装饰器的本质是一个闭包,而@仅仅是一个语法糖
-闭包的基础是python中的函数式一等对象
-理解闭包需要知道python如何识别变量所处的作用域
-自定义变量所处的作用域有三种:global,nonlocal,local

1.再谈变量作用域
·从内层函数的角度看,变量使用的两个维度
-是否能访问:LEGB规则(Local->Enclosed->Global->Built-in)
-是否能修改:需要声明才能修改
·变量作用域识别的三要素:
-出现位置:在哪里访问了
-赋值位置:在哪里赋值了
-声明类型:在哪里声明了
·三种变量作用域:
-局部:local
-全局:global
-非全局:nonlocal
例子:3种作用域,5次调用,3次赋值,0次声明

a = 1 #global
print(a)

def func_enclosed():
    a = 2 #nonlocal
    print(a)
    def func_local():
        a = 3  #local
        print(a)
    func_local()
    print(a)

func_enclosed()
print(a)

总结:无声明的情况下,赋值即私有,若外部有相同变量名则将其遮挡

a = 1 #global
print(a)

def func_enclosed():
    global a
    a = 2 #nonlocal
    print(a)
    def func_local():
        nonlocal a
        a = 3  #local
        print(a)
    func_local()
    print(a)

func_enclosed()
print(a)

#上述代码会报错,因为nonlocal找不到a
总结:nonlocal只能绑定在中间层定义的变量,如果中间层被声明外部全局变量,则会报错

为什么会有nonlocal的出现:
-nonlocal填补了global和local之间的空白
-nonlocal的出现其实是一种权衡利弊的结果:私有之安全封装,全局之灵活共享

2.闭包
-定义:延伸了作用域的函数(能访问定义体之外定义的费全局变量)
如果local层的函数能访问nonlocal中的变量,则称之为闭包
闭包是一种函数,它会保留定义函数时存在的外层非全局变量的绑定
例如:要实现这样一个函数:avg(x).即对一个序列求平均值,x是这个序列中的一个元素
这个序列是这样产生的:初识为空,每调用一次avg,传入一个x,序列就增加x元素
如:

avg(10):10,avg(11):10.5,avg(12):11
def make_averager():
    series = []
    def averager(new_value):
        series.append(new_value)
        total = sum(series)
        return total/len(series)
    return averager
avg = make_averager()
avg(10)······ 

上面的averger就是一个闭包,它可以访问nonlocal的变量series

优化一下上面的算法,sum一直在冗余:

def make_averager():
    cnt = 0
    total = 0
    def averager(new_value):
        nonlocal cnt,total
        cnt += 1
        total += new_value
        return total/len(series)
    return averager
avg = make_averager()
avg(10)······ 

注意:必须要加nonlocal,因为不加的话下面的cnt和上面的cnt不是同一个
而之前的程序seires不用加的原因是list是可变对象

2)闭包的作用:
-共享变量的时候避免使用了不安全的全局变量
-允许将函数与某系数据关联起来,类似于简化版面向对象编程
-相同代码每次生成的闭包,其延伸的作用域彼此都独立(计数器,注册表)
-函数的一部分行为在编写时无法预知,需要动态实现,同时又想保持接口一致性
-较低的内存开销:类的声明周期远大于闭包
-实现装饰器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值