基于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实现并行抓取整站40万条房价数据(可更换抓取城市)
Dec 14 Python
Python之Web框架Django项目搭建全过程
May 02 Python
Python 从一个文件中调用另一个文件的类方法
Jan 10 Python
pytorch自定义初始化权重的方法
Aug 17 Python
python做接口测试的必要性
Nov 20 Python
Tensorflow实现在训练好的模型上进行测试
Jan 20 Python
对python中arange()和linspace()的区别说明
May 03 Python
浅谈django框架集成swagger以及自定义参数问题
Jul 07 Python
Python pysnmp使用方法及代码实例
Aug 24 Python
使用python-cv2实现Harr+Adaboost人脸识别的示例
Oct 27 Python
浅析Python的命名空间与作用域
Nov 25 Python
MATLAB 如何求取离散点的曲率最大值
Apr 16 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
在smarty模板中使用PHP函数的方法
2011/04/23 PHP
基于php权限分配的实现代码
2013/04/28 PHP
php调整gif动画图片尺寸示例代码分享
2013/12/05 PHP
PHP实现多图上传(结合uploadify插件)思路分析
2016/11/30 PHP
autoIMG 基于jquery的图片自适应插件代码
2011/03/12 Javascript
JavaScript程序员应该知道的45个实用技巧
2014/03/04 Javascript
原生js仿jq判断当前浏览器是否为ie,精确到ie6~8
2014/08/30 Javascript
jQuery源码分析之jQuery中的循环技巧详解
2014/09/06 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
2014/11/13 Javascript
Node.js实现批量去除BOM文件头
2014/12/20 Javascript
JQUERY简单按钮轮换选中效果实现方法
2015/05/07 Javascript
js实现兼容性好的微软官网导航下拉菜单效果
2015/09/07 Javascript
基于RequireJS和JQuery的模块化编程日常问题解析
2016/04/14 Javascript
总结jQuery插件开发中的一些要点
2016/05/16 Javascript
JQuery EasyUI Layout 在from布局自适应窗口大小的实现方法
2016/05/28 Javascript
picLazyLoad 实现图片延时加载(包含背景图片)
2016/07/21 Javascript
js实现简易垂直滚动条
2017/02/22 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
Vue 中使用 CSS Modules优雅方法
2018/04/09 Javascript
举例讲解Python中装饰器的用法
2015/04/27 Python
使用PyInstaller将Python程序文件转换为可执行程序文件
2016/07/08 Python
怎样使用Python脚本日志功能
2016/08/14 Python
Python正则捕获操作示例
2017/08/19 Python
Python使用Selenium爬取淘宝异步加载的数据方法
2018/12/17 Python
Python常见数据类型转换操作示例
2019/05/08 Python
python shell命令行中import多层目录下的模块操作
2020/03/09 Python
Django实现前台上传并显示图片功能
2020/05/29 Python
Python 分布式缓存之Reids数据类型操作详解
2020/06/24 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
STP的判定过程
2012/10/01 面试题
中专生求职自荐信范文
2013/12/22 职场文书
创业计划书中包含的9个方面
2013/12/26 职场文书
中学劳技课教师的自我评价
2014/02/05 职场文书
2014年乡镇团委工作总结
2014/12/18 职场文书
小学生思想品德评语
2014/12/31 职场文书
自主招生学校推荐信范文
2015/03/26 职场文书