基于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实现的数据结构与算法之快速排序详解
Apr 22 Python
Python计算三维矢量幅度的方法
Jun 15 Python
Python安装第三方库及常见问题处理方法汇总
Sep 13 Python
Python2和Python3中print的用法示例总结
Oct 25 Python
pycharm运行和调试不显示结果的解决方法
Nov 30 Python
利用python Selenium实现自动登陆京东签到领金币功能
Oct 31 Python
python__new__内置静态方法使用解析
Jan 07 Python
Python安装依赖(包)模块方法详解
Feb 14 Python
在django admin详情表单显示中添加自定义控件的实现
Mar 11 Python
python 6.7 编写printTable()函数表格打印(完整代码)
Mar 25 Python
Python HTMLTestRunner可视化报告实现过程解析
Apr 10 Python
Django中的模型类设计及展示示例详解
May 29 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
基于HTTP长连接的&quot;服务器推&quot;技术的php 简易聊天室
2009/10/31 PHP
laravel框架 api自定义全局异常处理方法
2019/10/11 PHP
使用laravel根据用户类型来显示或隐藏字段
2019/10/17 PHP
List the Codec Files on a Computer
2007/06/18 Javascript
Javascript 面向对象之重载
2010/05/04 Javascript
JavaScript onkeypress事件入门实例(按下或按住一个键盘按键)
2014/10/17 Javascript
jquery 操作css样式、位置、尺寸方法汇总
2014/11/28 Javascript
JavaScript 实现打印,打印预览,打印设置
2014/12/30 Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
2015/09/16 Javascript
轻松学习jQuery插件EasyUI EasyUI创建树形网络(1)
2015/11/30 Javascript
初步使用bootstrap快速创建页面
2016/03/03 Javascript
jquery跟随屏幕滚动效果的实现代码
2016/04/13 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
详解ES6 Promise对象then方法链式调用
2018/10/20 Javascript
socket io与vue-cli的结合使用的示例代码
2018/11/01 Javascript
详解微信小程序-canvas绘制文字实现自动换行
2019/04/26 Javascript
一起写一个即插即用的Vue Loading插件实现
2019/10/31 Javascript
JavaScript oncopy事件用法实例解析
2020/05/13 Javascript
python修改操作系统时间的方法
2015/05/18 Python
python实现汉诺塔递归算法经典案例
2021/03/01 Python
一步步教你用Python实现2048小游戏
2017/01/19 Python
python生成词云的实现方法(推荐)
2017/06/13 Python
Python实现打砖块小游戏代码实例
2019/05/18 Python
python学习笔记之多进程
2020/08/06 Python
基于CSS3实现的几个小loading效果
2018/09/27 HTML / CSS
美国男士和女士奢侈品折扣手表购物网站:Certified Watch Store
2018/06/13 全球购物
奥地利度假券的专家:we-are.travel
2019/04/10 全球购物
是否有自动比较结构的方法
2015/06/03 面试题
新大陆软件面试题
2016/11/24 面试题
幼儿园数学教学反思
2014/02/02 职场文书
《我要的是葫芦》教学反思
2014/02/23 职场文书
利群广告词
2014/03/20 职场文书
五四青年节优秀演讲稿范文
2014/05/28 职场文书
证婚人婚礼致辞
2015/07/28 职场文书
vue3获取当前路由地址
2022/02/18 Vue.js
Java Spring Boot请求方式与请求映射过程分析
2022/06/25 Java/Android