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生成器的使用方法
Nov 21 Python
Python中input和raw_input的一点区别
Oct 21 Python
Python3使用requests登录人人影视网站的方法
May 11 Python
对python-3-print重定向输出的几种方法总结
May 11 Python
opencv python 傅里叶变换的使用
Jul 21 Python
使用Python机器学习降低静态日志噪声
Sep 29 Python
Python3.5 Json与pickle实现数据序列化与反序列化操作示例
Apr 29 Python
计算机二级python学习教程(1) 教大家如何学习python
May 16 Python
Python安装selenium包详细过程
Jul 23 Python
python3 enum模块的应用实例详解
Aug 12 Python
Pytorch保存模型用于测试和用于继续训练的区别详解
Jan 10 Python
PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解
Apr 16 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实现var_export的详细介绍
2013/06/20 PHP
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
2013/08/07 PHP
PHPExcel笔记, mpdf导出
2016/05/03 PHP
Prototype源码浅析 Enumerable部分(二)
2012/01/18 Javascript
javascrip关于继承的小例子
2013/05/10 Javascript
JavaScript递归操作实例浅析
2016/10/31 Javascript
JS无缝滚动效果实现方法分析
2016/12/21 Javascript
node.js中grunt和gulp的区别详解
2017/07/17 Javascript
js中getBoundingClientRect的作用及兼容方案详解
2018/02/01 Javascript
JavaScript设计模式之调停者模式实例详解
2018/02/03 Javascript
Angular PWA使用的Demo示例
2019/01/31 Javascript
javascript中join方法实例讲解
2019/02/21 Javascript
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&amp;平移轮播效果
2019/08/16 Javascript
给Python入门者的一些编程建议
2015/06/15 Python
Python和JavaScript间代码转换的4个工具
2016/02/22 Python
Django接受前端数据的几种方法总结
2016/11/04 Python
Python 列表(List) 的三种遍历方法实例 详解
2017/04/15 Python
Python获取当前路径实现代码
2017/05/08 Python
python之文件读取一行一行的方法
2018/07/12 Python
pycharm的console输入实现换行的方法
2019/01/16 Python
用python做游戏的细节详解
2019/06/25 Python
Python tkinter常用操作代码实例
2020/01/03 Python
利用Python裁切tiff图像且读取tiff,shp文件的实例
2020/03/10 Python
Python爬虫实例——scrapy框架爬取拉勾网招聘信息
2020/07/14 Python
h5调用摄像头的实现方法
2016/06/01 HTML / CSS
Converse匡威法国官网:美国著名帆布鞋品牌
2018/12/05 全球购物
意大利网上药房:Farmacia 33
2020/01/27 全球购物
新闻记者个人求职的自我评价
2013/11/28 职场文书
历史系自荐信范文
2013/12/24 职场文书
投标单位介绍信
2014/01/09 职场文书
体育系毕业生求职自荐信
2014/04/16 职场文书
2015年民兵整组工作总结
2015/07/24 职场文书
公司出差管理制度范本
2015/08/05 职场文书
小学语文教学反思范文
2016/03/03 职场文书
vue实现同时设置多个倒计时
2021/05/20 Vue.js
Golang表示枚举类型的详细讲解
2021/09/04 Golang