基于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 httplib,smtplib使用方法
Sep 06 Python
python登陆asp网站页面的实现代码
Jan 14 Python
Python中使用MELIAE分析程序内存占用实例
Feb 18 Python
在Linux系统上安装Python的Scrapy框架的教程
Jun 11 Python
python3实现基于用户的协同过滤
May 31 Python
机器学习之KNN算法原理及Python实现方法详解
Jul 09 Python
详解用python自制微信机器人,定时发送天气预报
Mar 25 Python
python批量修改图片尺寸,并保存指定路径的实现方法
Jul 04 Python
SELENIUM自动化模拟键盘快捷键操作实现解析
Oct 28 Python
使用Python实现正态分布、正态分布采样
Nov 20 Python
Tensorflow实现部分参数梯度更新操作
Jan 23 Python
浅析Python 序列化与反序列化
Aug 05 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语法(1)
2006/10/09 PHP
ThinkPHP模板Switch标签用法示例
2014/06/30 PHP
PHP通过API获取手机号码归属地
2015/05/28 PHP
Ajax中的JSON格式与php传输过程全面解析
2017/11/14 PHP
PHP call_user_func和call_user_func_array函数的简单理解与应用分析
2019/11/25 PHP
基于PHP的登录和注册的功能的实现
2020/08/06 PHP
IE中jscript/javascript的条件编译
2006/09/07 Javascript
Javascript与flash交互通信基础教程
2008/08/07 Javascript
JSON JQUERY模板实现说明
2010/07/03 Javascript
JS动态添加与删除select中的Option对象(示例代码)
2013/12/20 Javascript
使用jQuery实现的掷色子游戏动画效果
2014/03/14 Javascript
jquery移除、绑定、触发元素事件使用示例详解
2014/04/10 Javascript
jquery实现像栅栏一样左右滑出式二级菜单效果代码
2015/08/24 Javascript
JS动态插入并立即执行回调函数的方法
2016/04/21 Javascript
javaScript事件学习小结(四)event的公共成员(属性和方法)
2016/06/09 Javascript
javascript 四十条常用技巧大全
2016/09/09 Javascript
在knockoutjs 上自己实现的flux(实例讲解)
2017/12/18 Javascript
Bootstrap导航菜单点击后无法自动添加active的处理方法
2018/08/10 Javascript
JS实现获取当前所在周的周六、周日示例分析
2019/05/11 Javascript
elementUi vue el-radio 监听选中变化的实例代码
2019/06/28 Javascript
javascript设计模式 ? 抽象工厂模式原理与应用实例分析
2020/04/09 Javascript
[34:08]2018DOTA2亚洲邀请赛3月29日 小组赛B组 VP VS EG
2018/03/30 DOTA
Python urlopen()函数 示例分享
2014/06/12 Python
Python中字典和JSON互转操作实例
2015/01/19 Python
python爬虫beautifulsoup库使用操作教程全解(python爬虫基础入门)
2021/02/19 Python
表达自我的市场:Society6
2018/08/01 全球购物
27个经典Linux面试题及答案,你知道几个?
2013/01/10 面试题
成品仓管员岗位职责
2013/12/11 职场文书
表扬信格式
2014/01/12 职场文书
网吧消防安全制度
2014/01/28 职场文书
感恩父母的演讲稿
2014/05/06 职场文书
前台接待岗位职责范本
2015/04/03 职场文书
个人道歉信大全
2019/04/11 职场文书
详解Laravel服务容器的优势
2021/05/29 PHP
Android中的Launch Mode详情
2022/06/05 Java/Android
JS前端监控采集用户行为的N种姿势
2022/07/23 Javascript