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版微信红包分配算法
May 04 Python
python实现ping的方法
Jul 06 Python
详解python 拆包可迭代数据如tuple, list
Dec 29 Python
浅谈numpy数组中冒号和负号的含义
Apr 18 Python
Sanic框架请求与响应实例分析
Jul 16 Python
python实现嵌套列表平铺的两种方法
Nov 08 Python
带你认识Django
Jan 15 Python
Python 解决火狐浏览器不弹出下载框直接下载的问题
Mar 09 Python
Django后端分离 使用element-ui文件上传方式
Jul 12 Python
Python sqlalchemy时间戳及密码管理实现代码详解
Aug 01 Python
如何快速理解python的垃圾回收机制
Sep 01 Python
Python下opencv库的安装过程及问题汇总
Jun 11 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 SQL防注入代码集合
2008/04/25 PHP
破解图片防盗链的代码(asp/php)测试通过
2010/07/02 PHP
php创建sprite
2014/02/11 PHP
smarty简单入门实例
2014/11/28 PHP
PHP中mysqli_get_server_version()的实例用法
2020/02/03 PHP
页面使用密码保护代码
2013/04/10 Javascript
Extjs4中tree的拖拽功能(可以两棵树之间拖拽) 简单实例
2013/12/08 Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
2020/05/01 Javascript
[51:10]VP vs VGJ.S 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python内置数据类型详解
2014/08/18 Python
Django 导出 Excel 代码的实例详解
2017/08/11 Python
Python基于numpy灵活定义神经网络结构的方法
2017/08/19 Python
python使用pil进行图像处理(等比例压缩、裁剪)实例代码
2017/12/11 Python
python3.6.3+opencv3.3.0实现动态人脸捕获
2018/05/25 Python
Python 访问限制 private public的详细介绍
2018/10/16 Python
Python使用post及get方式提交数据的实例
2019/01/24 Python
实例讲解Python脚本成为Windows中运行的exe文件
2019/01/24 Python
django配置连接数据库及原生sql语句的使用方法
2019/03/03 Python
从0开始的Python学习016异常
2019/04/08 Python
Python 3 判断2个字典相同
2019/08/06 Python
使用Python测试Ping主机IP和某端口是否开放的实例
2019/12/17 Python
几款Python编译器比较与推荐(小结)
2020/10/15 Python
Python读写csv文件流程及异常解决
2020/10/20 Python
Python开发.exe小工具的详细步骤
2021/01/27 Python
Java里面有没有全局变量?为什么?
2015/02/06 面试题
杭州-飞时达软件有限公司.net笔面试
2012/04/28 面试题
检查接待方案
2014/02/27 职场文书
支部鉴定材料
2014/06/02 职场文书
师范类求职信
2014/06/21 职场文书
机电专业毕业生自我鉴定2014
2014/10/04 职场文书
志愿者事迹材料
2014/12/26 职场文书
迟到检讨书范文
2015/01/27 职场文书
2015夏季作息时间调整通知
2015/04/24 职场文书
复兴之路观后感
2015/06/02 职场文书
52条SQL语句教你性能优化
2021/05/25 MySQL
Win11怎么添加用户?Win11添加用户账户的方法
2022/07/15 数码科技