基于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中的__future__模块
Apr 27 Python
Python实现螺旋矩阵的填充算法示例
Dec 28 Python
python SSH模块登录,远程机执行shell命令实例解析
Jan 12 Python
python使用pil库实现图片合成实例代码
Jan 20 Python
tensorflow构建BP神经网络的方法
Mar 12 Python
对python3 一组数值的归一化处理方法详解
Jul 11 Python
对python实现二维函数高次拟合的示例详解
Dec 29 Python
Python学习笔记之集合的概念和简单使用示例
Aug 22 Python
Python字符串中添加、插入特定字符的方法
Sep 10 Python
pytorch中的inference使用实例
Feb 20 Python
Django中使用Json返回数据的实现方法
Jun 03 Python
python一些性能分析的技巧
Aug 30 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
967 个函式
2006/10/09 PHP
一个程序下载的管理程序(四)
2006/10/09 PHP
PHP 网页过期时间的控制代码
2009/06/29 PHP
PHP对表单提交特殊字符的过滤和处理方法汇总
2014/02/18 PHP
php 中奖概率算法实现代码
2017/01/25 PHP
php提供实现反射的方法和实例代码
2019/09/17 PHP
js创建数据共享接口——简化框架之间相互传值
2011/10/23 Javascript
动态加载js和css(外部文件)
2013/04/17 Javascript
javascript中attribute和property的区别详解
2014/06/05 Javascript
处理文本部分内容的TextRange对象应用实例
2014/07/29 Javascript
JQuery中层次选择器用法实例详解
2015/05/18 Javascript
简单分析javascript面向对象与原型
2015/05/21 Javascript
js实现仿爱微网两级导航菜单效果代码
2015/08/31 Javascript
JS+CSS实现简单的二级下拉导航菜单效果
2015/09/21 Javascript
举例说明如何为JavaScript的方法参数设置默认值
2015/11/17 Javascript
js判断主流浏览器类型和版本号的简单实现代码
2016/05/26 Javascript
JS中append字符串包含onclick无效传递参数失败的解决方案
2016/12/26 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
2017/02/19 Javascript
使用OPENLAYERS3实现点选的方法
2020/09/24 Javascript
详解layui中的树形关于取值传值问题
2018/01/16 Javascript
在HTML文档中嵌入JavaScript的四种方法
2018/05/07 Javascript
webpack4手动搭建Vue开发环境实现todoList项目的方法
2019/05/16 Javascript
python在windows下实现ping操作并接收返回信息的方法
2015/03/20 Python
在python中使用xlrd获取合并单元格的方法
2018/12/26 Python
Python查找数组中数值和下标相等的元素示例【二分查找】
2019/02/13 Python
Python文件读写常见用法总结
2019/02/22 Python
python实现在函数图像上添加文字和标注的方法
2019/07/08 Python
Anaconda 查看、创建、管理和使用python环境的方法
2019/12/03 Python
Python3的socket使用方法详解
2020/02/18 Python
Brasty波兰:香水、化妆品、手表网上商店
2019/04/15 全球购物
莫斯科珠宝厂官方网站:Miuz
2020/09/19 全球购物
活动志愿者自荐信
2014/01/27 职场文书
观看《周恩来的四个昼夜》思想汇报
2014/09/12 职场文书
护理工作个人总结
2015/03/03 职场文书
茶花女读书笔记
2015/06/29 职场文书
PyTorch的Debug指南
2021/05/07 Python