Python-for循环的内部机制


Posted in Python onJune 12, 2020

Python中,使用for循环可以迭代容器对象中的元素,这里容器对象包括是列表(list)、元组(tuple)、字典(dict)、集合(set)等。但是,为什么这些对象可以使用for循环进行操作呢?

首先,定义一个简单的类尝试一下:

class TestRange:
  def __init__(self, num):
    self.num = num
for i in TestRange(10):
  print(i)

# 输出
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: 'TestRange' object is not iterable

错误信息提示,'TestRange' object 不是可迭代的对象。那么,什么才是可迭代的对象呢?

在可迭代的对象中,需要实现一个__iter__魔法方法,而且这个方法的返回值需要是一个迭代器。那么,什么是迭代器呢?

迭代器只需要实现__next__魔法方法。

以列表(list)为例:

>>> nums = [13,12,33]
>>> iter_ret = nums.__iter__() # x有此方法,说明list是可迭代的,而且该方法返回一个迭代器
>>> iter_ret
<list_iterator object at 0x100f32198>

>>> iter_ret.__next__()
13
>>> iter_ret.__next__()
12
>>> iter_ret.__next__()
33
>>> iter_ret.__next__()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration

分析:

如上所示,列表nums中实现了__iter__方法,而且返回一个迭代器(iterator),迭代器中实现了__next__方法。在不断调用__next__的过程中,就是在不断返回nums中的元素,直到出现StopIteration的错误。

其实,for语句的作用与此类似。for语句的内部机制为

  • 先判断对象是否为可迭代对象,即是否存在__iter__方法,如果存在则调用__iter__方法,返回一个迭代器;否则,直接抛出TypeError异常;
  • 不断地调用迭代器的__next__方法,每次调用按顺序迭代获取当前的值;
  • 迭代完所有元素,就抛出异常 StopIteration,这个异常 python 解释器自己会处理;

前面的 TestRange 报错是因为它没有实现迭代器协议里面的这两个方法,现在继续改进:

class TestRange:
  def __init__(self, _max):
    self.i = 0
    self._max = _max

  def __iter__(self):
    return self

  def __next__(self):
    if self.i < self._max:
      i = self.i
      self.i += 1
      return i
    else:
      # 达到停止条件时,抛出此异常
      raise StopIteration()

# 进行测试
for i in TestRange(3):
  print(i)
# 输出
 0
 1
 2

分析:

因为这个类中,已经实现了__next__方法,所以基于这个类所创建的对象,本身就是一个迭代器。又因为可迭代对象需要有__iter__方法,而且返回一个迭代器,所以__iter__返回对象本身self即可。

总结

到此这篇关于Python-for循环的内部机制的文章就介绍到这了,更多相关python for 循环内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python抓取京东价格分析京东商品价格走势
Jan 09 Python
python字符串连接方式汇总
Aug 21 Python
Python访问MySQL封装的常用类实例
Nov 11 Python
详解Python各大聊天系统的屏蔽脏话功能原理
Dec 01 Python
详解使用 pyenv 管理多个版本 python 环境
Oct 19 Python
VSCode下配置python调试运行环境的方法
Apr 06 Python
Python tkinter label 更新方法
Oct 11 Python
使用pygame编写Flappy bird小游戏
Mar 14 Python
利用python绘制数据曲线图的实现
Apr 09 Python
Python bisect模块原理及常见实例
Jun 17 Python
使用PyCharm官方中文语言包汉化PyCharm
Nov 18 Python
Python 带星号(* 或 **)的函数参数详解
Feb 23 Python
Python Scrapy图片爬取原理及代码实例
Jun 12 #Python
Python Scrapy多页数据爬取实现过程解析
Jun 12 #Python
Selenium自动化测试工具使用方法汇总
Jun 12 #Python
Python使用socketServer包搭建简易服务器过程详解
Jun 12 #Python
Django之腾讯云短信的实现
Jun 12 #Python
python相对企业语言优势在哪
Jun 12 #Python
keras实现基于孪生网络的图片相似度计算方式
Jun 11 #Python
You might like
PHP面向对象编程快速入门
2006/12/14 PHP
写php分页时出现的Fatal error的解决方法
2011/04/18 PHP
php中explode与split的区别介绍
2012/10/03 PHP
php学习笔记之基础知识
2014/11/08 PHP
PHP让网站移动访问更加友好方法
2019/02/14 PHP
PhpStorm2020.1 安装 debug - Postman 调用的详细教程
2020/08/17 PHP
Swoole源码中如何查询Websocket的连接问题详解
2020/08/30 PHP
THREE.JS入门教程(2)着色器-上
2013/01/24 Javascript
jquery easyui中treegrid用法的简单实例
2014/02/18 Javascript
jQuery判断复选框是否勾选的原理及示例
2014/05/21 Javascript
JavaScript检测上传文件大小的方法
2015/07/22 Javascript
设计模式中的组合模式在JavaScript程序构建中的使用
2016/05/18 Javascript
Laravel中常见的错误与解决方法小结
2016/08/30 Javascript
AngularJS 应用身份认证的技巧总结
2016/11/07 Javascript
微信小程序 点击控件后选中其它反选实例详解
2017/02/21 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
Three.js利用性能插件stats实现性能监听的方法
2017/09/25 Javascript
vue的状态管理模式vuex
2017/11/30 Javascript
Vue Element使用icon图标教程详解(第三方)
2018/02/07 Javascript
微信小程序常用赋值方法小结
2019/04/30 Javascript
如何解决日期函数new Date()浏览器兼容性问题
2019/09/11 Javascript
基于vue-cli3和element实现登陆页面
2019/11/13 Javascript
使用python BeautifulSoup库抓取58手机维修信息
2013/11/21 Python
Python中max函数用法实例分析
2015/07/17 Python
linux下python中文乱码解决方案详解
2019/08/28 Python
python推导式的使用方法实例
2021/02/28 Python
美国领先的在线旅游网站:Orbitz
2018/11/05 全球购物
全球500多个机场的接送服务:Suntransfers
2019/06/03 全球购物
护士个人简历自荐信
2013/10/18 职场文书
学习新党章思想汇报
2014/01/09 职场文书
2014年高三毕业生自我评价
2014/01/11 职场文书
素质拓展感言
2014/01/29 职场文书
教师职业道德事迹材料
2014/08/18 职场文书
2014年高中生自我评价范文
2014/09/26 职场文书
硕士毕业论文导师评语
2014/12/31 职场文书
52条SQL语句教你性能优化
2021/05/25 MySQL