基于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语言的优雅之处
Jul 04 Python
python+selenium+autoit实现文件上传功能
Aug 23 Python
Python爬取十篇新闻统计TF-IDF
Jan 03 Python
教你用一行Python代码实现并行任务(附代码)
Feb 02 Python
python tensorflow学习之识别单张图片的实现的示例
Feb 09 Python
Python实现绘制双柱状图并显示数值功能示例
Jun 23 Python
python3实现带多张图片、附件的邮件发送
Aug 10 Python
使用OpenCV实现仿射变换—平移功能
Aug 29 Python
Python BeautifulReport可视化报告代码实例
Apr 13 Python
零基础学Python之前需要学c语言吗
Jul 21 Python
浅析关于Keras的安装(pycharm)和初步理解
Oct 23 Python
2021年值得向Python开发者推荐的VS Code扩展插件
Jan 25 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+HTML+JavaScript+Css实现简单爬虫开发
2016/03/28 PHP
通过百度地图获取公交线路的站点坐标的js代码
2012/05/11 Javascript
jquery创建表格(自动增加表格)代码分享
2013/12/25 Javascript
详解JavaScript基于面向对象之创建对象(1)
2015/12/10 Javascript
点评js异步加载的4种方式
2015/12/22 Javascript
极力推荐一款小巧玲珑的可视化编辑器bootstrap-wysiwyg
2016/05/27 Javascript
js原生之焦点图转换加定时器实例
2016/12/12 Javascript
jquery Easyui Datagrid实现批量操作(编辑,删除,添加)
2017/02/20 Javascript
深入nodejs中流(stream)的理解
2017/03/27 NodeJs
JS作用域链详解
2017/06/26 Javascript
基于ajax和jsonp的原生封装(实例)
2017/10/16 Javascript
jQuery中的for循环var与let的区别
2018/04/21 jQuery
原生JS实现列表子元素顺序反转的方法分析
2018/07/02 Javascript
详解JS浏览器事件循环机制
2019/03/27 Javascript
layui实现下拉复选功能的例子(包括数据的回显与上传)
2019/09/24 Javascript
小程序实现左滑删除的效果的实例代码
2020/10/19 Javascript
Flask的图形化管理界面搭建框架Flask-Admin的使用教程
2016/06/13 Python
Python爬取当当、京东、亚马逊图书信息代码实例
2017/12/09 Python
Python中shapefile转换geojson的示例
2019/01/03 Python
python列表生成器迭代器实例解析
2019/12/19 Python
python实现udp聊天窗口
2020/03/31 Python
filter使用python3代码进行迭代元素的实例详解
2020/12/03 Python
使用CSS3的背景渐变Text Gradient 创建文字颜色渐变
2014/08/19 HTML / CSS
瑞典最大的儿童用品网上商店:pinkorblue.se
2021/03/09 全球购物
销售总监工作职责
2013/11/21 职场文书
2014学雷锋活动心得体会
2014/03/10 职场文书
超市开店计划书
2014/04/26 职场文书
爱与责任演讲稿
2014/05/20 职场文书
我的中国梦演讲稿600字
2014/08/19 职场文书
2014幼儿教师个人工作总结
2014/12/03 职场文书
2016国庆节67周年寄语
2015/12/07 职场文书
如何让2019年上半年的工作总结更出色!
2019/07/01 职场文书
创业计划书之面包店
2019/09/17 职场文书
创业计划书之情侣餐厅
2019/09/29 职场文书
详细谈谈MYSQL中的COLLATE是什么
2021/06/11 MySQL
Python的代理类实现,控制访问和修改属性的权限你都了解吗
2022/03/21 Python