基于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实现从web抓取文档的方法
Sep 26 Python
Python正则匹配判断手机号是否合法的方法
Dec 09 Python
如何通过python的fabric包完成代码上传部署
Jul 29 Python
django自定义模板标签过程解析
Dec 14 Python
Python面向对象编程基础实例分析
Jan 17 Python
Python闭包装饰器使用方法汇总
Jun 29 Python
python 如何将office文件转换为PDF
Sep 22 Python
Python通过fnmatch模块实现文件名匹配
Sep 30 Python
python入门教程之基本算术运算符
Nov 13 Python
pymongo insert_many 批量插入的实例
Dec 05 Python
python爬虫scrapy框架的梨视频案例解析
Feb 20 Python
如何在Python中创建二叉树
Mar 30 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
PHP版网站缓存加快打开速度的方法分享
2012/06/03 PHP
详解PHP内置访问资源的超时时间 time_out file_get_contents read_file
2013/06/03 PHP
对PHP新手的一些建议(PHP学习经验总结)
2014/08/20 PHP
javascript 多级checkbox选择效果
2009/08/20 Javascript
Javascript中获取出错代码所在文件及行数的代码
2010/09/23 Javascript
Javascript 倒计时源代码.(时.分.秒) 详细注释版
2011/05/09 Javascript
JS继承 笔记
2011/07/13 Javascript
jquery如何改变html标签的样式(两种实现方法)
2013/01/16 Javascript
js创建表单元素并使用submit进行提交
2014/08/14 Javascript
谈谈encodeURI和encodeURIComponent以及escape的区别与应用
2015/11/24 Javascript
jQuery滚动加载图片实现原理
2015/12/14 Javascript
javascript数组去重小结
2016/03/07 Javascript
深入浅析javascript中的作用域(推荐)
2016/07/19 Javascript
浅谈JS的基础类型与引用类型
2016/09/13 Javascript
Node.js如何响应Ajax的POST请求并且保存为JSON文件详解
2017/03/10 Javascript
jQuery实现点击关注和取消功能
2017/07/03 jQuery
JS和jQuery通过this获取html标签中的属性值(实例代码)
2017/09/11 jQuery
vue中的router-view组件的使用教程
2018/10/23 Javascript
vue实现微信浏览器左上角返回按钮拦截功能
2020/01/18 Javascript
Vue中通过属性绑定为元素绑定style行内样式的实例代码
2020/04/30 Javascript
使用python在校内发人人网状态(人人网看状态)
2014/02/19 Python
python简单实现旋转图片的方法
2015/05/30 Python
Python编程之字符串模板(Template)用法实例分析
2017/07/22 Python
jupyter notebook引用from pyecharts.charts import Bar运行报错
2020/04/23 Python
Python绘制热力图示例
2019/09/27 Python
Django REST Framework之频率限制的使用
2019/09/29 Python
wordpress添加Html5的表单验证required方法小结
2020/08/18 HTML / CSS
Tory Burch德国官网:美国时尚生活品牌
2018/01/03 全球购物
美国最大的存储市场:SpareFoot
2018/07/23 全球购物
数控专业大学生的自我鉴定
2013/11/13 职场文书
乌鸦喝水教学反思
2014/02/07 职场文书
《曹刿论战》教学反思
2014/03/02 职场文书
经济管理毕业生求职信
2014/03/15 职场文书
2014年乡镇民政工作总结
2014/12/02 职场文书
教师节祝酒词
2015/08/11 职场文书
毕业生就业推荐表自我鉴定
2019/06/20 职场文书