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比较2个xml内容的方法
May 11 Python
Python使用django搭建web开发环境
Jun 09 Python
python验证码识别教程之利用滴水算法分割图片
Jun 05 Python
python爬虫之urllib3的使用示例
Jul 09 Python
python 简单照相机调用系统摄像头实现方法 pygame
Aug 03 Python
Flask 上传自定义头像的实例详解
Jan 09 Python
使用TensorFlow搭建一个全连接神经网络教程
Feb 06 Python
Python如何使用OS模块调用cmd
Feb 27 Python
浅谈python opencv对图像颜色通道进行加减操作溢出
Jun 03 Python
pandas实现导出数据的四种方式
Dec 13 Python
解决Jupyter-notebook不弹出默认浏览器的问题
Mar 30 Python
浅谈Python协程asyncio
Jun 20 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代码运行时间查看类代码分享
2011/08/06 PHP
PHP中全局变量global和$GLOBALS[]的区别分析
2012/08/06 PHP
wamp下修改mysql访问密码的解决方法
2013/05/07 PHP
总结PHP内存释放以及垃圾回收
2018/03/29 PHP
javascript的事件描述
2006/09/08 Javascript
自写的一个jQuery圆角插件
2010/10/26 Javascript
基于ajax实现文件上传并显示进度条
2015/08/03 Javascript
微信小程序 网络API发起请求详解
2016/11/09 Javascript
discuz表情的JS提取方法分析
2017/03/22 Javascript
微信小程序云开发(数据库)详解
2019/05/17 Javascript
vue实现简单的日历效果
2020/09/24 Javascript
JavaScript队列结构Queue实现过程解析
2020/03/07 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
vue中defineProperty和Proxy的区别详解
2020/11/30 Vue.js
[03:30]DOTA2完美“圣”典精彩集锦
2016/12/27 DOTA
[42:24]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第一场 11.01
2020/11/02 DOTA
Python使用scrapy采集时伪装成HTTP/1.1的方法
2015/04/08 Python
详解字典树Trie结构及其Python代码实现
2016/06/03 Python
python+pyqt实现12306图片验证效果
2017/10/25 Python
Python实现合并同一个文件夹下所有txt文件的方法示例
2018/04/26 Python
python向已存在的excel中新增表,不覆盖原数据的实例
2018/05/02 Python
解决Python安装后pip不能用的问题
2018/06/12 Python
python操作docx写入内容,并控制文本的字体颜色
2020/02/13 Python
Python把图片转化为pdf代码实例
2020/07/28 Python
阿联酋优惠券服务:Living Kool
2019/12/12 全球购物
Python文件操作的面试题
2013/06/22 面试题
俄语专业毕业生推荐信
2013/10/28 职场文书
网络宣传方案
2014/03/15 职场文书
奥巴马胜选演讲稿
2014/05/15 职场文书
党员个人批评与自我批评
2014/10/14 职场文书
暂住证证明
2015/06/19 职场文书
网络安全倡议书(3篇)
2019/09/18 职场文书
导游词之云南丽江-泸沽湖
2019/09/26 职场文书
详解Python小数据池和代码块缓存机制
2021/04/07 Python
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis
Python使用psutil库对系统数据进行采集监控的方法
2021/08/23 Python