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之折腾一下目录
Oct 24 Python
Python中内建函数的简单用法说明
May 05 Python
Python 自动刷博客浏览量实例代码
Jun 14 Python
python3下使用cv2.imwrite存储带有中文路径图片的方法
May 10 Python
Python OpenCV处理图像之图像直方图和反向投影
Jul 10 Python
Python连接Redis的基本配置方法
Sep 13 Python
python绘制多个子图的实例
Jul 07 Python
python科学计算之numpy——ufunc函数用法
Nov 25 Python
Python unittest单元测试openpyxl实现过程解析
May 27 Python
django模型类中,null=True,blank=True用法说明
Jul 09 Python
如何使用Python调整图像大小
Sep 26 Python
Python3的进程和线程你了解吗
Mar 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
DC宇宙的第一个英雄,堪称动漫史鼻祖,如今成为美国文化的象征
2020/04/09 欧美动漫
php中通过正则表达式下载内容中的远程图片的函数代码
2012/01/10 PHP
php静态文件返回304技巧分享
2015/01/06 PHP
php简单操作mysql数据库的类
2015/04/16 PHP
orm获取关联表里的属性值
2016/04/17 PHP
php7安装yar扩展的方法详解
2017/08/03 PHP
IE8 浏览器Cookie的处理
2009/01/31 Javascript
Document 对象的常用方法
2009/07/31 Javascript
javascript 带有滚动条的表格,标题固定,带排序功能.
2009/11/13 Javascript
JS实现图片横向滚动效果示例代码
2013/09/04 Javascript
现代 JavaScript 开发编程风格Idiomatic.js指南中文版
2014/05/28 Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
2016/05/17 Javascript
概述VUE2.0不可忽视的很多变化
2016/09/25 Javascript
js实现功能比较全面的全选和多选
2017/03/02 Javascript
AngularJs 最新验证手机号码的实例,成功测试通过
2017/11/26 Javascript
Vue-cropper 图片裁剪的基本原理及思路讲解
2018/04/17 Javascript
微信小程序开发之转发分享功能
2019/10/22 Javascript
VUE 单页面使用 echart 窗口变化时的用法
2020/07/30 Javascript
[20:30]职业巡回赛回顾
2018/08/09 DOTA
Python实现将json文件中向量写入Excel的方法
2018/03/26 Python
python 读取txt中每行数据,并且保存到excel中的实例
2018/04/29 Python
python删除文件夹下相同文件和无法打开的图片
2019/07/16 Python
Django REST framework 单元测试实例解析
2019/11/07 Python
Django在Model保存前记录日志实例
2020/05/14 Python
Python读写锁实现实现代码解析
2020/11/28 Python
HTML5中的Web Notification桌面右下角通知功能的实现
2018/04/19 HTML / CSS
老海军美国官网:Old Navy
2016/09/05 全球购物
.NET里面如何取得当前的屏幕分辨率
2012/12/06 面试题
汇科协同Java笔试题
2012/03/31 面试题
2014财产信托协议书范本
2014/11/18 职场文书
采购员岗位职责
2015/02/03 职场文书
鼋头渚导游词
2015/02/05 职场文书
企业承诺书格式范文
2015/04/28 职场文书
情况说明书怎么写
2015/10/08 职场文书
Python中requests做接口测试的方法
2021/05/30 Python
Redis集群的关闭与重启操作
2021/07/07 Redis