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两个整数相除得到浮点数值的方法
Mar 18 Python
python随机生成指定长度密码的方法
Apr 04 Python
Python合并两个字典的常用方法与效率比较
Jun 17 Python
python+matplotlib实现动态绘制图片实例代码(交互式绘图)
Jan 20 Python
python语音识别实践之百度语音API
Aug 30 Python
python3学生名片管理v2.0版
Nov 29 Python
Python使用lambda表达式对字典排序操作示例
Jul 25 Python
python基于K-means聚类算法的图像分割
Oct 30 Python
python+Django实现防止SQL注入的办法
Oct 31 Python
Python random模块制作简易的四位数验证码
Feb 01 Python
PHP基于phpqrcode类库生成二维码过程解析
May 28 Python
Python描述数据结构学习之哈夫曼树篇
Sep 07 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
剧场版动画《PSYCHO-PASS 3 FIRST INSPECTOR》3月27日日本上映!
2020/03/06 日漫
php利用curl抓取新浪微博内容示例
2014/04/27 PHP
Smarty中常用变量操作符汇总
2014/10/27 PHP
php利用cookies实现购物车的方法
2014/12/10 PHP
PHP中SSO Cookie登录分析和实现
2015/11/06 PHP
thinkPHP下的widget扩展用法实例分析
2015/12/26 PHP
利用Laravel生成Gravatar头像地址的优雅方法
2017/12/30 PHP
php实现数组中出现次数超过一半的数字的统计方法
2018/10/14 PHP
Laravel中正确地返回HTTP状态码方法示例
2019/09/10 PHP
thinkphp5框架前后端分离项目实现分页功能的方法分析
2019/10/08 PHP
用js实现小球的自由移动代码
2013/04/22 Javascript
基于JS实现的笛卡尔乘积之商品发布
2016/05/13 Javascript
JS如何生成一个不重复的ID的函数
2016/12/25 Javascript
如何利用JQuery实现从底部回到顶部的功能
2016/12/27 Javascript
html5 canvas 详细使用教程
2017/01/20 Javascript
JavaScript中创建对象的7种模式详解
2017/02/21 Javascript
Jquery中.bind()、.live()、.delegate()和.on()之间的区别详解
2017/08/01 jQuery
js实现网页的两个input标签内的数值加减(示例代码)
2017/08/15 Javascript
Node.js 利用cheerio制作简单的网页爬虫示例
2018/03/01 Javascript
JavaScript获取用户所在城市及地理位置
2018/04/21 Javascript
Vue 监听元素前后变化值实例
2020/07/29 Javascript
vue使用svg文件补充-svg放大缩小操作(使用d3.js)
2020/09/22 Javascript
Python ValueError: invalid literal for int() with base 10 实用解决方法
2015/06/21 Python
Python获取邮件地址的方法
2015/07/10 Python
python merge、concat合并数据集的实例讲解
2018/04/12 Python
利用python库在局域网内传输文件的方法
2018/06/04 Python
Python初学者需要注意的事项小结(python2与python3)
2018/09/26 Python
适合Python初学者的一些编程技巧
2020/02/12 Python
美术师范毕业生自荐信
2013/11/16 职场文书
餐饮业的创业计划书范文
2013/12/26 职场文书
社区健康教育实施方案
2014/03/18 职场文书
2014年国庆节演讲稿精选范文1500字
2014/09/25 职场文书
2014年保险业务员工作总结
2014/12/23 职场文书
主婚人致辞精选
2015/07/28 职场文书
小学班主任工作随笔
2015/08/15 职场文书
MySQL中distinct和count(*)的使用方法比较
2021/05/26 MySQL