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实现tcp自动重连
Jul 02 Python
基于Django与ajax之间的json传输方法
May 29 Python
python矩阵转换为一维数组的实例
Jun 05 Python
python RabbitMQ 使用详细介绍(小结)
Nov 08 Python
Django框架模板语言实例小结【变量,标签,过滤器,继承,html转义】
May 23 Python
python内存动态分配过程详解
Jul 15 Python
python datetime中strptime用法详解
Aug 29 Python
wxPython实现分隔窗口
Nov 19 Python
Python基于DB-API操作MySQL数据库过程解析
Apr 23 Python
python thrift 实现 单端口多服务的过程
Jun 08 Python
2021年的Python 时间轴和即将推出的功能详解
Jul 27 Python
Python matplotlib图例放在外侧保存时显示不完整问题解决
Jul 28 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
在WordPress中实现发送http请求的相关函数解析
2015/12/29 PHP
php实现爬取和分析知乎用户数据
2016/01/26 PHP
Zend Studio使用技巧两则
2016/04/01 PHP
php加速缓存器opcache,apc,xcache,eAccelerator原理与配置方法实例分析
2020/03/02 PHP
jQuery 一个图片切换的插件
2011/10/09 Javascript
NodeJs中的非阻塞方法介绍
2012/06/05 NodeJs
为什么要在引入的css或者js文件后面加参数的详细讲解
2013/05/03 Javascript
js获取input标签的输入值实现代码
2013/08/05 Javascript
js 将json字符串转换为json对象的方法解析
2013/11/13 Javascript
js,jquery滚动/跳转页面到指定位置的实现思路
2014/06/03 Javascript
jQuery EasyUI datagrid在翻页以后仍能记录被选中行的实现代码
2016/08/15 Javascript
浅谈EasyUI常用控件的禁用方法
2016/11/09 Javascript
Jquery循环截取字符串的方法(多出的字符串处理成&quot;...&quot;)
2016/11/28 Javascript
jQuery取得元素标签名称小结(附代码)
2017/08/16 jQuery
layui之table checkbox初始化时选中对应选项的方法
2019/09/02 Javascript
Vue中错误图片的处理的实现代码
2019/11/07 Javascript
python使用wxPython打开并播放wav文件的方法
2015/04/24 Python
Python绘制3D图形
2018/05/03 Python
Python简单定义与使用二叉树示例
2018/05/11 Python
Django代码性能优化与Pycharm Profile使用详解
2018/08/26 Python
pytorch 实现删除tensor中的指定行列
2020/01/13 Python
Python如何向SQLServer存储二进制图片
2020/06/08 Python
浅析python中的del用法
2020/09/02 Python
Python中过滤字符串列表的方法
2020/12/22 Python
以特惠价提供在线奢侈品购物:FRMODA.com
2018/01/25 全球购物
员工考核管理制度
2014/02/02 职场文书
分公司经理任命书
2014/06/05 职场文书
公共机构节能宣传周活动总结
2014/07/09 职场文书
田径运动会通讯稿
2014/09/13 职场文书
四风问题个人剖析材料
2014/10/07 职场文书
中层干部考核评语
2015/01/04 职场文书
仓库统计员岗位职责
2015/04/14 职场文书
2019最新版试用期劳动合同模板!
2019/07/04 职场文书
python字符串的一些常见实用操作
2022/04/06 Python
PostgreSQL基于pgrouting的路径规划处理方法
2022/04/18 PostgreSQL
Oracle删除归档日志及添加定时任务
2022/06/28 Oracle