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实现抓取城市的PM2.5浓度和排名
Mar 19 Python
Python中的进程分支fork和exec详解
Apr 11 Python
在Django的URLconf中使用多个视图前缀的方法
Jul 18 Python
Python升级导致yum、pip报错的解决方法
Sep 06 Python
python使用itchat实现手机控制电脑
Feb 22 Python
python3.x实现base64加密和解密
Mar 28 Python
python程序快速缩进多行代码方法总结
Jun 23 Python
python函数的万能参数传参详解
Jul 26 Python
运用PyTorch动手搭建一个共享单车预测器
Aug 06 Python
Django中自定义模型管理器(Manager)及方法
Sep 23 Python
python Matplotlib模块的使用
Sep 16 Python
python matplotlib工具栏源码探析二之添加、删除内置工具项的案例
Feb 25 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/10/09 PHP
php基础知识:类与对象(2) 自动加载对象
2006/12/13 PHP
phpmyadmin导入(import)文件限制的解决办法
2009/12/11 PHP
PHP读取txt文件的内容并赋值给数组的代码
2011/11/03 PHP
Thinkphp调用Image类生成缩略图的方法
2015/03/07 PHP
PHP中实现crontab代码分享
2015/03/26 PHP
详解PHP的Yii框架中扩展的安装与使用
2016/04/01 PHP
visual studio code 调试php方法(图文详解)
2017/09/15 PHP
jquery miniui 教程 表格控件 合并单元格应用
2012/11/25 Javascript
js获取单选框或复选框值及操作
2012/12/18 Javascript
JS中Iframe之间传值的方法
2013/03/11 Javascript
使用jQuery异步加载 JavaScript脚本解决方案
2014/04/20 Javascript
js 获取时间间隔实现代码
2014/05/12 Javascript
js父页面与子页面不同时显示的方法
2014/10/16 Javascript
js中日期的加减法
2015/05/06 Javascript
JavaScript实现自动变换表格边框颜色
2015/05/08 Javascript
Vue组件BootPage实现简单的分页功能
2016/09/12 Javascript
JavaScript引用类型Object常见用法实例分析
2018/08/08 Javascript
小程序组件之仿微信通讯录的实现代码
2018/09/12 Javascript
微信小程序实现左右列表联动
2020/05/19 Javascript
vue实现简易图片左右旋转,上一张,下一张组件案例
2020/07/31 Javascript
js实现弹幕墙效果
2020/12/10 Javascript
[02:34]DOTA2亚洲邀请赛 BG战队出场宣传片
2015/03/09 DOTA
Java编程迭代地删除文件夹及其下的所有文件实例
2018/02/10 Python
Python设计模式之简单工厂模式实例详解
2019/01/22 Python
详解Python logging调用Logger.info方法的处理过程
2019/02/12 Python
Ubuntu16.04安装python3.6.5步骤详解
2020/01/10 Python
selenium WebDriverWait类等待机制的实现
2020/03/18 Python
浏览器实现移动端高性能css3动画(开启gpu加速)
2013/12/23 HTML / CSS
老海军美国官网:Old Navy
2016/09/05 全球购物
美国女孩服装购物网站:Justice
2017/03/04 全球购物
银行自荐信范文
2013/10/07 职场文书
晚会开幕词
2015/01/28 职场文书
行政助理岗位职责
2015/02/10 职场文书
档案管理员岗位职责
2015/02/12 职场文书
元素水平垂直居中的方式
2021/03/31 HTML / CSS