详解Python循环作用域与闭包


Posted in Python onMarch 21, 2019

前言

首先来看一段代码

x_list = [i for i in range(30)]
y_list = [i for i in range(10, 20)]
for y in y_list:
  x_list = filter(lambda a: a != y, x_list)
x_list = list(x_list)
print(x_list)
print(len(x_list))

这段代码会输出什么呢?

正确答案是一个长度为29的List。

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
29

但是实际上,上述代码我们想要表达的意图是从x_list中剔除所有在y_list中的元素。为什么在实际情况下,最终只会剔除一个元素呢?这主要与Python的作用域机制有关。

Python作用域机制

Python与其他语言不同,Python没有循环作用域这个说法。Python的作用域遵循LEGB原则

  1. L, local ? 在lambda函数内或者def函数内部的变量
  2. E, Enclosing-function ? 闭包的作用域
  3. G,Global ? 全局作用域
  4. B, Build-in ? 内建作用域

 为了证明Python没有循环作用域,可以通过下面一段代码验证

for i in range(10):
  pass
print(i)

运行代码,发现可以正常运行,运行结果i==9。由此可以证明Python不存在循环作用域,循环变量属于全局作用域。

基于上述结论,就可以很好地说明为什么上述的filter函数最终只去掉了一个元素。

因为filter函数是一个惰性函数,因此在循环过程中并不会进行实际运算,而当循环完成,需要实际输出的时候,此时全局作用域环境下的i已经变为了一个固定值19,因此最终只有19可以从x_list中去掉。

解决方案——闭包

面对上述问题,我们有两个解决方案。

第一个解决方案——避免惰性求值。可以发现,问题的根源在于filter函数是一个惰性求值函数,因此造成了这个问题。可以通过强制求值运算,强制每一次循环都进行filter操作,从而实现正常的筛选操作。代码如下所示。

x_list = [i for i in range(30)]
y_list = [i for i in range(10, 20)]
for y in y_list:
  x_list = list(filter(lambda a: a != y, x_list))
x_list = list(x_list)
print(x_list)
print(len(x_list))

第二个解决方案——闭包。有时候我们不想放弃惰性求值这个特性,那么我们就需要引入更高级的函数式编程思想——闭包。

因为Python支持函数式编程语法,可以将函数作为变量,因此可以很容易的实现闭包特性。

x_list = [i for i in range(30)]
y_list = [i for i in range(10, 20)]
def check(a, b):
  print('check')
  return a != b
for y in y_list:
  def x_filter(y):
    global x_list
    x_list = filter(lambda x: check(x, y), x_list)
  x_filter(y)
  print('loop')
x_list = list(x_list)
print(x_list)
print(len(x_list))

上面的代码为了证明惰性求值的有效性,因此稍微繁琐了一些。在实际场景中,check函数可以直接写成lambda函数的形式。

闭包之所以能解决循环作用域问题,是因为闭包有独立的作用域。因此即便是惰性求值,但是由于闭包作用于已经将临时变量进行了存储,因此依然可以正确进行筛选操作。

总结

Python与其他编程语言不同,不存在循环临时作用域,因此在某些场景下会出现与其它编程语言结果不一致的BUG。面对这种情况,我们一般可以通过两种方式来解决

1.避免惰性求值
2.使用闭包来保存循环临时变量

以上所述是小编给大家介绍的Python循环作用域与闭包详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python常用的日期时间处理方法示例
Feb 08 Python
python中字典(Dictionary)用法实例详解
May 30 Python
详细分析python3的reduce函数
Dec 05 Python
Python实现读取字符串按列分配后按行输出示例
Apr 17 Python
python调用百度REST API实现语音识别
Aug 30 Python
python实现旋转和水平翻转的方法
Oct 25 Python
jupyter notebook 中输出pyecharts图实例
Apr 23 Python
Python实现的远程文件自动打包并下载功能示例
Jul 12 Python
python多线程并发及测试框架案例
Oct 15 Python
python使用itchat模块给心爱的人每天发天气预报
Nov 25 Python
python3 中使用urllib问题以及urllib详解
Aug 03 Python
深入理解Python变量的数据类型和存储
Feb 01 Python
浅谈python之高阶函数和匿名函数
Mar 21 #Python
浅谈Python反射 & 单例模式
Mar 21 #Python
详解Python中is和==的区别
Mar 21 #Python
浅谈Python的条件判断语句if/else语句
Mar 21 #Python
python使用thrift教程的方法示例
Mar 21 #Python
在Python中如何传递任意数量的实参的示例代码
Mar 21 #Python
详解python使用turtle库来画一朵花
Mar 21 #Python
You might like
简单介绍下 PHP5 中引入的 MYSQLI的用途
2007/03/19 PHP
php使用递归函数实现数字累加的方法
2015/03/16 PHP
PHP 7安装使用体验之性能大提升,兼容性强,扩展支持不够(升级PHP要谨慎)
2017/07/27 PHP
PHP图像处理 imagestring添加图片水印与文字水印操作示例
2020/02/06 PHP
在JavaScript中实现命名空间
2006/11/23 Javascript
javascript jQuery $.post $.ajax用法
2008/07/09 Javascript
Mootools 1.2教程 滚动条(Slider)
2009/09/15 Javascript
鼠标右击事件代码(asp.net后台)
2011/01/27 Javascript
javascript中[]和{}对象使用介绍
2013/03/20 Javascript
JSONP跨域的原理解析及其实现介绍
2014/03/22 Javascript
javasctipt如何显示几分钟前、几天前等
2014/04/30 Javascript
javascript根据时间生成m位随机数最大13位
2014/10/30 Javascript
JavaScript获取网页、浏览器、屏幕高度和宽度汇总
2014/12/18 Javascript
原生js封装二级城市下拉列表的实现代码
2016/06/16 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
2016/06/21 Javascript
javaScript基础详解
2017/01/19 Javascript
微信小程序登录态控制深入分析
2017/04/12 Javascript
详解vue嵌套路由-query传递参数
2017/05/23 Javascript
基于AngularJS实现的工资计算器实例
2017/06/16 Javascript
Vue Cli与BootStrap结合实现表格分页功能
2017/08/18 Javascript
详解vue axios中文文档
2017/09/12 Javascript
js数组去重的N种方法(小结)
2018/06/07 Javascript
15分钟深入了解JS继承分类、原理与用法
2019/01/19 Javascript
Vuex持久化插件(vuex-persistedstate)解决刷新数据消失的问题
2019/04/16 Javascript
vue-cli3项目打包后自动化部署到服务器的方法
2020/09/16 Javascript
python实现决策树
2017/12/21 Python
对python 命令的-u参数详解
2018/12/03 Python
Python利用for循环打印星号三角形的案例
2020/04/12 Python
使用jupyter notebook将文件保存为Markdown,HTML等文件格式
2020/04/14 Python
Sephora丝芙兰澳洲官方网站:国际知名化妆品购物
2016/10/27 全球购物
电子商务专业自我鉴定
2013/12/18 职场文书
二年级班级文化建设方案
2014/05/10 职场文书
2014年个人售房协议书
2014/10/30 职场文书
2015年光棍节活动总结
2015/03/24 职场文书
教师节表彰会主持词
2015/07/06 职场文书
创新创业项目计划书该怎样写?
2019/08/13 职场文书