详解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 相关文章推荐
20招让你的Python飞起来!
Sep 27 Python
Python中shape计算矩阵的方法示例
Apr 21 Python
Python实现对一个函数应用多个装饰器的方法示例
Feb 09 Python
Python 实现引用其他.py文件中的类和类的方法
Apr 29 Python
python实现录音小程序
Oct 26 Python
Python实现的矩阵转置与矩阵相乘运算示例
Mar 26 Python
Python3.5基础之NumPy模块的使用图文与实例详解
Apr 24 Python
Python3内置模块之base64编解码方法详解
Jul 13 Python
在django中,关于session的通用设置方法
Aug 06 Python
Python + Flask 实现简单的验证码系统
Oct 01 Python
在Python中使用turtle绘制多个同心圆示例
Nov 23 Python
python数据分析之单因素分析线性拟合及地理编码
Jun 25 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+Html+缓存
2006/11/25 PHP
php单链表实现代码分享
2016/07/04 PHP
PHP PDOStatement::fetch讲解
2019/01/31 PHP
PHP面向对象类型约束用法分析
2019/06/12 PHP
JavaScript 获得选中文本内容的方法
2009/02/15 Javascript
JSON 学习之JSON in JavaScript详细使用说明
2010/02/23 Javascript
javascript中scrollTop详解
2015/04/13 Javascript
JavaScript数组和循环详解
2015/04/27 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
2015/09/26 Javascript
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
2016/12/14 Javascript
jquery实现下拉框左右选择功能
2017/02/21 Javascript
vue2.0结合Element实现select动态控制input禁用实例
2017/05/12 Javascript
详解React 在服务端渲染的实现
2017/11/16 Javascript
微信小程序实现手指触摸画板
2018/07/09 Javascript
jQuery实现的网站banner图片无缝轮播效果完整实例
2019/01/28 jQuery
Vue实现手机扫描二维码预览页面效果
2020/05/28 Javascript
Python中使用PIL库实现图片高斯模糊实例
2015/02/08 Python
在Linux系统上通过uWSGI配置Nginx+Python环境的教程
2015/12/25 Python
Python下实现的RSA加密/解密及签名/验证功能示例
2017/07/17 Python
python使用 zip 同时迭代多个序列示例
2019/07/06 Python
windows下Python安装、使用教程和Notepad++的使用教程
2019/10/06 Python
Python生成词云的实现代码
2020/01/14 Python
Python 实现自动获取种子磁力链接方式
2020/01/16 Python
python异常处理、自定义异常、断言原理与用法分析
2020/03/23 Python
Python多线程的退出控制实现
2020/08/10 Python
CSS3 渐变(Gradients)之CSS3 径向渐变
2016/07/08 HTML / CSS
HTML5 Canvas 绘图——使用 Canvas 绘制图形图文教程 使用html5 canvas 绘制精美的图
2015/08/31 HTML / CSS
Boden美国官网:英伦原创时装品牌
2017/07/03 全球购物
体验完美剃须:The Art of Shaving
2018/08/06 全球购物
Tuckernuck官网:经典的美国品质服装、鞋子和配饰
2021/01/11 全球购物
高中英语教学反思
2014/02/04 职场文书
学校文明单位申报材料
2014/05/06 职场文书
铣床操作工岗位职责
2014/06/13 职场文书
学校师德师风整改方案
2014/10/28 职场文书
房屋买卖协议样本
2014/11/16 职场文书
诚信承诺书
2015/01/19 职场文书