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基础教程之常用运算符
Aug 29 Python
零基础写python爬虫之爬虫的定义及URL构成
Nov 04 Python
python使用chardet判断字符串编码的方法
Mar 13 Python
利用python程序帮大家清理windows垃圾
Jan 15 Python
Mac中升级Python2.7到Python3.5步骤详解
Apr 27 Python
python的mysqldb安装步骤详解
Aug 14 Python
Python退火算法在高次方程的应用
Jul 26 Python
Python实现简单的用户交互方法详解
Sep 25 Python
Python一键查找iOS项目中未使用的图片、音频、视频资源
Aug 12 Python
python实现自动清理文件夹旧文件
May 10 Python
使用pipenv管理python虚拟环境的全过程
Sep 25 Python
python和Appium的移动端多设备自动化测试框架
Apr 26 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
一个很方便的 XML 类!!原创的噢
2006/10/09 PHP
yii实现图片上传及缩略图生成的方法
2014/12/04 PHP
php+redis实现商城秒杀功能
2020/11/19 PHP
php5对象复制、clone、浅复制与深复制实例详解
2019/08/14 PHP
JavaScript asp.net 获取当前超链接中的文本
2009/04/14 Javascript
JSON 入门指南 想了解json的朋友可以看下
2009/08/26 Javascript
js确定对象类型方法
2012/03/30 Javascript
jQuery.validate 常用方法及需要注意的问题
2013/03/20 Javascript
JavaScript获取多个数组的交集简单实例
2013/11/11 Javascript
js进行表单验证实例分析
2015/02/10 Javascript
ionic隐藏tabs的方法
2016/08/29 Javascript
HTML5基于Tomcat 7.0实现WebSocket连接并实现简单的实时聊天
2016/10/31 Javascript
Bootstrap CSS组件之按钮下拉菜单
2016/12/17 Javascript
对于Javascript 执行上下文的全面了解
2017/09/05 Javascript
node.js 利用流实现读写同步,边读边写的方法
2017/09/11 Javascript
vue2 mint-ui loadmore实现下拉刷新,上拉更多功能
2018/03/21 Javascript
浅析vue中常见循环遍历指令的使用 v-for
2018/04/18 Javascript
解决koa2 ctx.render is not a function报错问题
2018/08/07 Javascript
JS扁平化输出数组的2种方法解析
2019/09/17 Javascript
Vue项目接入Paypal实现示例详解
2020/06/04 Javascript
跟老齐学Python之玩转字符串(2)
2014/09/14 Python
Windows下安装python2.7及科学计算套装
2015/03/05 Python
Python中的各种装饰器详解
2015/04/11 Python
Python中的urllib模块使用详解
2015/07/07 Python
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
2019/04/01 Python
基于Django的乐观锁与悲观锁解决订单并发问题详解
2019/07/31 Python
解决Python3.8用pip安装turtle-0.0.2出现错误问题
2020/02/11 Python
python实现微信打飞机游戏
2020/03/24 Python
python用700行代码实现http客户端
2021/01/14 Python
Python 将代码转换为可执行文件脱离python环境运行(步骤详解)
2021/01/25 Python
CSS3 二级导航菜单的制作的示例
2018/04/02 HTML / CSS
团员个人的自我评价
2013/12/02 职场文书
秋季婚礼证婚词
2014/01/11 职场文书
毕业生面试求职信
2014/06/23 职场文书
2014年依法行政工作总结
2014/11/19 职场文书
2019学子的答谢词范本!
2019/07/05 职场文书