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的Django框架与认证系统整合的方法
Jul 24 Python
django轻松使用富文本编辑器CKEditor的方法
Mar 30 Python
Python计算斗牛游戏概率算法实例分析
Sep 26 Python
Python实现爬虫抓取与读写、追加到excel文件操作示例
Jun 27 Python
python机器学习库scikit-learn:SVR的基本应用
Jun 26 Python
python django 原生sql 获取数据的例子
Aug 14 Python
使用python实现kNN分类算法
Oct 16 Python
春节到了 教你使用python来抢票回家
Jan 06 Python
利用Python实现某OA系统的自动定位功能
May 27 Python
浅析Python迭代器的高级用法
Jul 16 Python
基于Python爬取搜狐证券股票过程解析
Nov 18 Python
tensorflow与numpy的版本兼容性问题的解决
Jan 08 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
ThinkPHP 3.2.3实现页面静态化功能的方法详解
2017/08/03 PHP
PHP调用全国天气预报数据接口查询天气示例
2019/02/20 PHP
自适应图片大小的弹出窗口
2006/07/27 Javascript
javascript 放大镜 v1.0 基于Yui2 实现的放大镜效果
2010/03/08 Javascript
玩转jQuery按钮 请告诉我你最喜欢哪些?
2012/01/08 Javascript
jquery 操作iframe的几种方法总结
2013/12/13 Javascript
Egret引擎开发指南之编译项目
2014/09/03 Javascript
js兼容火狐获取图片宽和高的方法
2015/05/21 Javascript
JS实现的新浪微博大厅文字内容滚动效果代码
2015/11/05 Javascript
轻松学习jQuery插件EasyUI EasyUI实现树形网络基本操作(2)
2015/11/30 Javascript
设置点击文本框或图片弹出日历控件的实现代码
2016/05/12 Javascript
详解nodejs 文本操作模块-fs模块(一)
2016/12/22 NodeJs
AngularJS中$http使用的简单介绍
2017/03/17 Javascript
详解angular element()方法使用
2017/04/08 Javascript
AngularJS实现自定义指令及指令配置项的方法
2017/11/20 Javascript
基于jQuery Ajax实现下拉框无刷新联动
2017/12/06 jQuery
使用jquery Ajax实现上传附件功能
2018/10/23 jQuery
原生javascript自定义input[type=radio]效果示例
2019/08/27 Javascript
微信内置浏览器图片查看器的代码实例
2019/10/08 Javascript
vue select 获取value和lable操作
2020/08/28 Javascript
在Python中使用第三方模块的教程
2015/04/27 Python
Django自定义认证方式用法示例
2017/06/23 Python
Python 列表理解及使用方法
2017/10/27 Python
Python实现的根据IP地址计算子网掩码位数功能示例
2018/05/23 Python
tensorflow: variable的值与variable.read_value()的值区别详解
2018/07/30 Python
Python对切片命名的实现方法
2018/10/16 Python
python去除拼音声调字母,替换为字母的方法
2018/11/28 Python
Python测试线程应用程序过程解析
2019/12/31 Python
浅析Python 抽象工厂模式的优缺点
2020/07/13 Python
基于Python的身份证验证识别和数据处理详解
2020/11/14 Python
厂长助理岗位职责
2013/12/27 职场文书
小区停车场管理制度
2014/01/27 职场文书
中文师范生自荐信
2014/01/30 职场文书
学习决心书
2014/03/11 职场文书
居委会工作总结2015
2015/05/18 职场文书
《攀登者》:“海拔8000米以上,你不能指望任何人”
2019/11/25 职场文书