设为首页 收藏本站
查看: 1037|回复: 0

[经验分享] Python 闭包

[复制链接]

尚未签到

发表于 2015-11-30 09:26:46 | 显示全部楼层 |阅读模式
什么是闭包?
  
  
  闭包(closure)是词法闭包(lexical closure)的简称。闭包不是新奇的概念,而是早在高级程序语言开始发展的年代就已产生。
  对闭包的理解大致分为两类,将闭包视为函数或者是由函数及其引用环境组成的复合体。


  • 前者认为闭包是在其词法上下文中引用了自动变量的函数。  

  • 后者认为闭包是显示表示引用外部环境,并将它与函数捆绑在一起而产生的复合体。
  所谓的自由变量是指局部变量以外的变量,同时自由变量的绑定可预知,所谓的绑定(binding)是指变量名称与其所代表的对象之间的联系。一些早期的计算机语言没有所谓封闭的函数,自由变量在运行时再进行绑定。对于那些拥有开放和封闭函数概念的计算机语言,人们需要一种新的术语来区分这两种函数,于是便有了术语闭包。
  一般而言,第二种观点相对更为准确。因为函数是一些可执行的代码,这些代码在定义函数时被固化,在运行时不会发生任何变化,所以一个函数只有一个实例。而闭包会随着引用环境变化而产生不同的实例。
  在 Python 以及大多数现代计算机语言中,所有函数都是封闭的,也就是说没有自由变量。于是对闭包的定义也从早期”对包含可预知绑定对象的自由变量的函数“变成了”可引用非激活环境的对象的函数“。对 Python 而言,自由变量被绑定到在外围作用域定义的变量。
  
  

Closure in Python
  
  
  闭包(closure)是一种引用了外部变量的函数对象,无论该变量所处的作用域是否还存在于内存中。
  举例来说,函数 generate_power_func 返回了另一个函数:
  

def generate_power_func(n):
  print "id(n): %X" %>  def nth_power(x):
  return x**n

  print "id(nth_power): %X" %>  return nth_power
  

  函数 nth_power 就是一个闭包,它可以访问定义在 generate_power_func 函数中的变量 n,显而易见如果缺少变量 n,函数 nth_power 将是一个不能执行的没有闭合的函数,这个不完整的函数 nth_power 需要变量 n 来让它变成一个完整的函数对象,这种函数就是闭包,换句话说是变量 n 封闭了函数 nth_power
  现在我们调用一下函数 generate_power_func,并将调用结果返回给一个变量 raised_to_4
  

>>> raised_to_4 = generate_power_func(4)  
id(n): 28F8A4
  
id(nth_power): B6CB4570
  
>>> repr(rasied_to_4)
  
''
  

  结果是调用函数 generate_power_func(4) 将生成一个 nth_power 函数对象。现在我们将函数 generate_power_func 函数从全局命名空间删除。
  

>>> del generate_power_func  

  然后调用闭包函数 raised_to_4
  

>>> rasied_to_4(2)  
16
  

  奇迹出现了,销毁函数 generate_power_func 并没有影响到函数 raised_to_4。我们在函数 generate_power_func 中定义变量 n,并且我们已经销毁了函数 generate_power_func,为什么 raised_to_4 会知道变量 n=4
  这是因为函数对象 nth_power 是由 generate_power_func 产生的一个闭包,闭包会保留来自外围作用域变量的信息。
  
  

__closure__ 属性和 cell 对象
  
  
  Python 中函数对象都拥有一个 __closure__ 属性。
  __closure__ 对象返回一个由 cell 对象组成的元组,cell 对象记录了定义在外围作用域的变量信息。
  

>>> raised_to_4.__closure__  
(,)
  
>>> type(raised_to_4.__closure__[0])
  

  
>>> raised_to_4.__closure__[0].cell_contents
  
4
  

  正如所见,__closure__ 属性引用了一个 int 对象,这个 int 对象就是变量 n。对于那些不是闭包的函数对象来说,__closure__ 属性值为 None。
  
  

See Also
  Python Closures Explained
  Closures in Python
  闭包的概念、形式与应用

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145166-1-1.html 上篇帖子: [原创]如何编写多个阻塞队列连接下的多生产者多消费者的Python程序 下篇帖子: Python——eventlet.wsgi
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表