第13.2节 关于闭包

一、 概念
闭包(Closure)又称词法闭包(Lexical Closure)或函数闭包(function closures),闭包与函数嵌套有关,在《第5.5节 函数递归、嵌套及样例》中老猿介绍了函数嵌套,函数中嵌套的函数称为嵌套函数、外层的函数称为封闭函数。闭包简单来说就是一个嵌套函数中引用了封闭函数定义的变量,并且该函数可以在其定义环境外即封闭函数外被执行。这样的嵌套函数我们称之为闭包。嵌套函数使用的封闭函数的变量称为自由变量。
在闭包的情况下,在调用封闭函数后,会将嵌套函数返回给调用方,调用结束后,封闭函数执行结束,其执行时的自由变量传递给了嵌套函数保存,而嵌套函数被调用方保存,意味着调用方获取了嵌套函数及其调用时自由变量的值,意味着嵌套函数与封闭函数脱离了关系独立存在。因此闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
要创建闭包,必须满足以下条件:
• 必须包含一个嵌套函数
• 嵌套函数必须引用封闭函数中定义的自由变量,在引用前需用nonlocal关键字进行声明
• 封闭函数的调用结果必须将嵌套函数作为其返回值

二、 闭包的好处

  1. 取代硬编码中的常量
    由于闭包中可以通过封闭函数的自由变量传递值给闭包函数,而闭包函数中该自由变量的值可以保持不变,这样可以不使用常量来实现,又具有灵活性,通过不同的闭包实例使用不同的自由变量值。
  2. 避免使用全局值,并提供某种形式的数据隐藏
    在闭包实例中自由变量可以在脱离封闭函数的情况下保持不变,从而取代了全局变量的作用。
  3. 实现面向对象
    闭包可以允许不同的实例实际执行存在差异,这样可以在不同类中调用同一封闭函数传递不同自由变量的值而实现不同的执行效果,这样调用方无需关注是通过哪个类进行调用,从而实现了一定程度的封装。

三、 案例

>>> def cal(op):
    def calop(op1,op2):
        nonlocal op
        if op=='+':return op1+op2
        elif op=='-':return op1-op2
        elif op=='*':return op1*op2
        elif op=='/':return op1/op2
        else: raise ValueError('运算符必须是+-*/中的一个')
    return calop

>>> add =cal('+')
>>> minus=cal('-')
>>> add(1,2)
3
>>> minus(1,2)
-1
>>>

四、 补充说明

  1. 所有函数对象都有一个 closure 属性,如果这个函数是一个闭包函数,那么会返回的是一个由 cell 对象组成的元组。cell 对象具有 cell_contents 属性,存储了闭包中的自由变量。这也解释了为什么局部变量在脱离函数之后,还可以在函数之外被访问,因为它存储在了闭包的 cell_contents 中;
  2. 闭包之所以又称为词法闭包,是因为自由变量的作用域在定义时确认了,而不是在执行时决定。这符合词法作用域(Lexical Scoping)的概念。词法作用域取决于源码,通过静态分析就能够确定,因此,词法作用域也叫做静态作用域;
  3. Python中闭包最常用的场景就是装饰器,关于装饰器在此不展开介绍,将在中高级课程部分再介绍。

老猿Python,跟老猿学Python!
博客地址:https://blog.csdn.net/LaoYuanPython

请大家多多支持,点赞、评论和加关注!谢谢!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LaoYuanPython

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值