基于Python闭包及其作用域详解


Posted in Python onAugust 28, 2017

关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记

如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包(closure),而这个被内部函数引用的变量则被成为自由变量

闭包和函数调用没多少相关,而是关于使用定义在其他作用域的变量

命名空间和作用域

我们把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系。在 Python 中,作用域实际上可以看做是“在当前上下文的位置,获取命名空间变量的规则”。在 Python 代码执行的任意位置,都至少存在三层嵌套的作用域:

最内层作用域,最先搜索,包含所有局部变量(Python 默认所有变量声明均为局部变量)

所有包含当前上下文的外层函数的作用域,由内而外依次搜索,这里包含的是非局部也非全局的变量

一直向上搜索,直到当前模块的全局变量

最外层,最后搜索的,内置(built-in)变量

scopes = {
 "local": {"locals": None,
    "non-local": {"locals": None,
       "global": {"locals": None,
         "built-in": ["built-ins"]}}},
}

除了默认的局部变量声明方式,Python还有global和nonlocal两种类型的声明(nonlocal是Python3.x之后才有的),其中nonlocal是指最内层之外,global以内的变量。必须强调的是,最内层局部作用域对外层作用域的变量只有只读(read-only)的访问权限。比如下列的例子

x = 100
def main():
 x += 1
 print (x)
main()
UnboundLocalError Traceback (most recent call last)
<ipython-input-2-9ed43e483a17> in <module>()
  3 x += 1
  4 print(x)
----> 5 main()
<ipython-input-2-9ed43e483a17> in main()
  1 x = 100
  2 def main():
----> 3 x += 1
  4 print(x)
  5 main()
UnboundLocalError: local variable 'x' referenced before assignment

这里抛出UnboundLocalError,是因为main()函数内部的作用域对于全局变量x仅有只读权限,想要在main()中对x进行改变,不会影响全局变量,而是会创建一个新的局部变量,显然无法对还未创建的局部变量直接使用x += 1, 因为x未绑定到任何对象上。如果想要获得全局变量的完全引用,则需要global声明:

x = 100
def main():
 global x
 x += 1
 print(x)
main()
print(x) # 全局变量已被改变

# result: 
# 101
# 101

闭包

闭包和函数调用没多少相关,而是关于使用定义在其他作用域的变量。

看了上面的Python作用域规则后,我们可以仿照JavaScript写一个计数器的闭包:

"""
/* JavaScript Closure example */
var inc = function(){ 
 var x = 0;
 return function(){
 console.log(x++);
 };
};
var inc1 = inc()
var inc2 = inc()
"""

# Python
def inc():
 x = 0
 def inner():
  nonlocal x
  x += 1
  print(x)
 return inner
inc1 = inc()
inc2 = inc()
inc1()
inc1()
inc1()
inc2()


# result:
# 1
# 2
# 3
# 1

在这里,全局环境下不能获取到inc()中的局部变量x的,但是我们返回了inc()内部函数inner(),而inner()对inc()中的局部变量是有访问权限的。也就是说inner()将inc()局部作用域打包发送给了inc1和 inc2,从而使他们各自独立拥有了一块封闭起来的作用域,不受其他运行环境和全局变量的影响,因此称之为闭包。

上述代码中inc1和inc2各自有一块封闭起来的作用域,可以通过Online Python Tutor 可视化运行工具看相应的运行结果

基于Python闭包及其作用域详解

这篇基于Python闭包及其作用域详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python基于smtplib实现异步发送邮件服务
May 28 Python
Python编程中装饰器的使用示例解析
Jun 20 Python
Python创建二维数组实例(关于list的一个小坑)
Nov 07 Python
Python实现简易版的Web服务器(推荐)
Jan 29 Python
python之mock模块基本使用方法详解
Jun 27 Python
python flask 如何修改默认端口号的方法步骤
Jul 12 Python
windows中安装Python3.8.0的实现方法
Nov 19 Python
Python 跨.py文件调用自定义函数说明
Jun 01 Python
属性与 @property 方法让你的python更高效
Sep 21 Python
如何使用PyCharm引入需要使用的包的方法
Sep 22 Python
python小技巧——将变量保存在本地及读取
Nov 13 Python
Python实现王者荣耀自动刷金币的完整步骤
Jan 22 Python
利用Python查看目录中的文件示例详解
Aug 28 #Python
Python如何通过subprocess调用adb命令详解
Aug 27 #Python
Python中序列的修改、散列与切片详解
Aug 27 #Python
Python正确重载运算符的方法示例详解
Aug 27 #Python
深入学习Python中的上下文管理器与else块
Aug 27 #Python
python利用MethodType绑定方法到类示例代码
Aug 27 #Python
Python中使用haystack实现django全文检索搜索引擎功能
Aug 26 #Python
You might like
Could not load type System.ServiceModel.Activation.HttpModule解决办法
2012/12/29 PHP
php无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
PHP CodeIgniter框架的工作原理研究
2015/03/30 PHP
PHP微信支付结果通知与回调策略分析
2019/01/10 PHP
php实现网页上一页下一页翻页过程详解
2019/06/28 PHP
JqGrid web打印实现代码
2011/05/31 Javascript
JS前端框架关于重构的失败经验分享
2013/03/17 Javascript
javascript变量作用域使用中常见错误总结
2013/03/26 Javascript
使用JQuery快速实现Tab的AJAX动态载入(实例讲解)
2013/12/11 Javascript
jQuery的live()方法对hover事件的处理示例
2014/02/27 Javascript
jQuery.extend()、jQuery.fn.extend()扩展方法示例详解
2014/05/08 Javascript
javascript编写贪吃蛇游戏
2015/07/07 Javascript
JQuery实现的按钮倒计时效果
2015/12/23 Javascript
实例详解jQuery Mockjax 插件模拟 Ajax 请求
2016/01/12 Javascript
js获取html的span标签的值方法(超简单)
2016/07/26 Javascript
KnockoutJS 3.X API 第四章之事件event绑定
2016/10/10 Javascript
angular学习之ngRoute路由机制
2017/04/12 Javascript
javascript 正则表达式分组、断言详解
2017/04/20 Javascript
用ES6写全屏滚动插件的示例代码
2018/05/02 Javascript
vue filters的使用详解
2018/06/11 Javascript
详解ES6中的 Set Map 数据结构学习总结
2018/11/06 Javascript
你或许不知道的一些npm实用技巧
2019/07/04 Javascript
五分钟搞懂Vuex实用知识(小结)
2019/08/12 Javascript
vue-model实现简易计算器
2020/08/17 Javascript
[36:52]DOTA2真视界:基辅特锦赛总决赛
2017/05/21 DOTA
Python实现拷贝/删除文件夹的方法详解
2018/08/29 Python
python实现udp聊天窗口
2020/03/31 Python
详解tf.device()指定tensorflow运行的GPU或CPU设备实现
2021/02/20 Python
英国最大的老式糖果店:A Quarter Of
2017/04/08 全球购物
经典c++面试题六
2012/01/18 面试题
个人简历自我评价
2014/02/02 职场文书
周年庆典主持词
2014/04/02 职场文书
小学班主任自我评价
2015/03/11 职场文书
挂职锻炼工作总结2015
2015/05/28 职场文书
实施意见格式范本
2015/06/05 职场文书
银行客户经理培训心得体会
2016/01/09 职场文书