基于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解析xml文件实例分享
Dec 04 Python
约瑟夫问题的Python和C++求解方法
Aug 20 Python
Python3如何解决字符编码问题详解
Apr 23 Python
Python获取指定文件夹下的文件名的方法
Feb 06 Python
PyQt5主窗口动态加载Widget实例代码
Feb 07 Python
numpy 对矩阵中Nan的处理:采用平均值的方法
Oct 30 Python
python读取目录下所有的jpg文件,并显示第一张图片的示例
Jun 13 Python
pandas 选取行和列数据的方法详解
Aug 08 Python
Pytorch修改ResNet模型全连接层进行直接训练实例
Sep 10 Python
python数据库操作mysql:pymysql、sqlalchemy常见用法详解
Mar 30 Python
keras CNN卷积核可视化,热度图教程
Jun 22 Python
python 自动刷新网页的两种方法
Apr 20 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 MemCached 高级缓存应用代码
2010/08/05 PHP
二进制交叉权限微型php类分享
2014/02/07 PHP
PHP基于socket实现客户端和服务端通讯功能
2017/07/13 PHP
Yii2.0多文件上传实例说明
2017/07/24 PHP
laravel5.4生成验证码的实例讲解
2017/08/05 PHP
js Html结构转字符串形式显示代码
2011/11/15 Javascript
表单的焦点顺序tabindex和对应enter键提交
2013/01/04 Javascript
自动设置iframe大小的jQuery代码
2013/09/11 Javascript
JS中把字符转成ASCII值的函数示例代码
2013/11/21 Javascript
详谈javascript中DOM的基本属性
2015/02/26 Javascript
JavaScript对数组进行随机重排的方法
2015/07/22 Javascript
javascript比较两个日期相差天数的方法
2015/07/24 Javascript
Bootstrap选项卡动态切换效果
2016/11/28 Javascript
ES6中Class类的静态方法实例小结
2017/10/28 Javascript
详解NODEJS基于FFMPEG视频推流测试
2017/11/17 NodeJs
详解如何在React组件“外”使用父组件的Props
2018/01/12 Javascript
完美解决mui框架off-canvas侧滑超出部分隐藏无法滚动的问题
2018/01/25 Javascript
基于jQuery实现无缝轮播与左右点击效果
2018/05/13 jQuery
vue中v-model的应用及使用详解
2018/06/27 Javascript
layui自己添加图片按钮并点击跳转页面的例子
2019/09/14 Javascript
vue项目实现图片上传功能
2019/12/23 Javascript
解决vue组件没显示,没起作用,没报错,但该显示的组件没显示问题
2020/09/02 Javascript
在Python程序中操作文件之flush()方法的使用教程
2015/05/24 Python
python开发之tkinter实现图形随鼠标移动的方法
2015/11/11 Python
Django中多种重定向方法使用详解
2019/07/17 Python
python实现全排列代码(回溯、深度优先搜索)
2020/02/26 Python
TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
2020/04/08 Python
PyQT5速成教程之Qt Designer介绍与入门
2020/11/02 Python
html5中为audio标签增加停止按钮动作实现方法
2013/01/04 HTML / CSS
Bibloo罗马尼亚网站:女装、男装、童装及鞋子和配饰
2019/07/20 全球购物
会计师职业生涯规划范文
2014/02/18 职场文书
捐助倡议书范文
2014/04/15 职场文书
房地产推广策划方案
2014/05/19 职场文书
小学生学习保证书
2015/02/26 职场文书
2015年依法行政工作总结
2015/04/29 职场文书
React自定义hook的方法
2022/06/25 Javascript