基于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 相关文章推荐
php使用递归与迭代实现快速排序示例
Jan 23 Python
python使用cPickle模块序列化实例
Sep 25 Python
python 回调函数和回调方法的实现分析
Mar 23 Python
Pycharm技巧之代码跳转该如何回退
Jul 16 Python
Python numpy 点数组去重的实例
Apr 18 Python
Python中对数组集进行按行打乱shuffle的方法
Nov 08 Python
python实现各种插值法(数值分析)
Jul 30 Python
Python利用 utf-8-sig 编码格式解决写入 csv 文件乱码问题
Feb 21 Python
Anaconda3中的Jupyter notebook添加目录插件的实现
May 18 Python
使用OpenCV获取图像某点的颜色值,并设置某点的颜色
Jun 02 Python
python SOCKET编程基础入门
Feb 27 Python
对pytorch中x = x.view(x.size(0), -1) 的理解说明
Mar 03 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生成静态页
2006/11/25 PHP
PHP之密码加密的几种方式
2015/07/29 PHP
Yii多表联合查询操作详解
2016/06/02 PHP
PHP HTTP 认证实例详解
2016/11/03 PHP
PHP实现的操作数组类库定义与用法示例
2019/05/24 PHP
Javascript 获取字符串字节数的多种方法
2009/06/02 Javascript
基于jquery创建的一个图片、视频缓冲的效果样式插件
2012/08/28 Javascript
js统计录入文本框中字符的个数并加以限制不超过多少
2014/05/23 Javascript
jquery操作angularjs对象
2015/06/26 Javascript
Javascript中replace()小结
2015/09/30 Javascript
解决js函数闭包内存泄露问题的办法
2016/01/25 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
JS实现自动阅读单词(有道单词本添加功能)
2016/11/14 Javascript
jQuery中Chosen三级联动功能实例代码
2017/03/07 Javascript
jQuery实现的动态文字变化输出效果示例【附演示与demo源码下载】
2017/03/24 jQuery
Angular.JS读取数据库数据调用完整实例
2019/07/02 Javascript
微信公众号平台接口开发 获取微信服务器IP地址方法解析
2019/08/14 Javascript
解决layui中onchange失效以及form动态渲染失效的问题
2019/09/27 Javascript
js使用文档就绪函数动态改变页面内容示例【innerHTML、innerText】
2019/11/07 Javascript
JavaScript 生成唯一ID的几种方式
2021/02/19 Javascript
python制作爬虫爬取京东商品评论教程
2016/12/16 Python
python3.5+tesseract+adb实现西瓜视频或头脑王者辅助答题
2018/01/17 Python
python让列表倒序输出的实例
2018/06/25 Python
python脚本调用iftop 统计业务应用流量的思路详解
2019/10/11 Python
使用python实现哈希表、字典、集合操作
2019/12/22 Python
Python实现电视里的5毛特效实例代码详解
2020/05/15 Python
CSS3+Sprite实现僵尸行走动画特效源码
2016/01/27 HTML / CSS
eDreams加拿大:廉价航班、酒店和度假
2019/03/29 全球购物
ABOUT YOU匈牙利:500个最受欢迎的时尚品牌
2019/07/19 全球购物
解决python 输出到csv 出现多空行的情况
2021/03/24 Python
说明书范文
2014/05/07 职场文书
小学感恩节活动策划方案
2014/10/06 职场文书
离婚协议书样本
2015/01/26 职场文书
上帝也疯狂观后感
2015/06/09 职场文书
JavaScript数组 几个常用方法总结
2021/11/11 Javascript
redis调用二维码时的不断刷新排查分析
2022/04/01 Redis