详解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的地形三维可视化Matplotlib和gdal使用实例
Dec 09 Python
Django使用HttpResponse返回图片并显示的方法
May 22 Python
详解python分布式进程
Oct 08 Python
python list格式数据excel导出方法
Oct 31 Python
用Python实现读写锁的示例代码
Nov 05 Python
Python骚操作之动态定义函数
Mar 26 Python
Python实现搜索算法的实例代码
Jan 02 Python
浅谈tensorflow中张量的提取值和赋值
Jan 19 Python
将自己的数据集制作成TFRecord格式教程
Feb 17 Python
python中有帮助函数吗
Jun 19 Python
解决keras GAN训练是loss不发生变化,accuracy一直为0.5的问题
Jul 02 Python
基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码
Feb 18 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
PHP-MySQL教程归纳总结
2008/06/07 PHP
php如何解决无法上传大于8M的文件问题
2014/03/10 PHP
php线性表的入栈与出栈实例分析
2015/06/12 PHP
javascript中常用编程知识
2013/04/08 Javascript
nullJavascript中创建对象的五种方法实例
2013/05/07 Javascript
ie8本地图片上传预览示例代码
2014/01/12 Javascript
javascript 判断整数方法分享
2014/12/16 Javascript
谈谈对offsetleft兼容性的理解
2015/11/11 Javascript
老生常谈JavaScript数组的用法
2016/06/10 Javascript
BootStrap智能表单实战系列(八)表单配置json详解
2016/06/13 Javascript
JS动态给对象添加事件的简单方法
2016/07/19 Javascript
微信小程序-消息提示框实例
2016/11/24 Javascript
JavaScript实现汉字转换为拼音的库文件示例
2016/12/22 Javascript
微信小程序 本地存储及登录页面处理实例详解
2017/01/11 Javascript
从零开始学习Node.js系列教程之基于connect和express框架的多页面实现数学运算示例
2017/04/13 Javascript
深入理解Vue生命周期、手动挂载及挂载子组件
2017/09/27 Javascript
React根据宽度自适应高度的示例代码
2017/10/11 Javascript
Angular2管道Pipe及自定义管道格式数据用法实例分析
2017/11/29 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
2017/12/11 Javascript
vue+element实现批量删除功能的示例
2018/02/28 Javascript
jQuery实现的模仿雨滴下落动画效果
2018/12/11 jQuery
小程序最新获取用户昵称和头像的方法总结
2019/09/23 Javascript
浅谈Python由__dict__和dir()引发的一些思考
2017/10/30 Python
python实现求最长回文子串长度
2018/01/22 Python
在python里协程使用同步锁Lock的实例
2019/02/19 Python
sklearn-SVC实现与类参数详解
2019/12/10 Python
电脑教师的教学自我评价
2013/11/26 职场文书
工地门卫岗位职责
2013/12/30 职场文书
大学生实习思想汇报
2014/01/12 职场文书
音乐专业自荐信
2014/02/07 职场文书
招聘专员岗位职责
2014/03/07 职场文书
摄影专业毕业生求职信
2014/03/13 职场文书
新文化运动的基本口号
2014/06/21 职场文书
高中生期中考试失利检讨书
2014/10/23 职场文书
婚前协议书范本
2014/10/27 职场文书
2014年技术部工作总结
2014/12/12 职场文书