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去掉字符串中重复字符的方法
Feb 27 Python
Python中使用动态变量名的方法
May 06 Python
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)
Jun 09 Python
深入理解python中的闭包和装饰器
Jun 12 Python
在Python web中实现验证码图片代码分享
Nov 09 Python
Django项目开发中cookies和session的常用操作分析
Jul 03 Python
python数据结构学习之实现线性表的顺序
Sep 28 Python
Python函数的参数常见分类与用法实例详解
Mar 30 Python
深入浅析Python中的迭代器
Jun 04 Python
浅谈Python类中的self到底是干啥的
Nov 11 Python
nginx+uwsgi+django环境搭建的方法步骤
Nov 25 Python
Python字符串格式化常用手段及注意事项
Jun 17 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中Cannot send session cache limiter 的问题的方法
2007/04/27 PHP
php中强制下载文件的代码(解决了IE下中文文件名乱码问题)
2011/05/09 PHP
PHP闭包函数传参及使用外部变量的方法
2016/03/15 PHP
在laravel中使用Symfony的Crawler组件分析HTML
2017/06/19 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
JavaScript的目的分析
2007/01/05 Javascript
js数值和和字符串进行转换时可以对不同进制进行操作
2014/03/05 Javascript
Javascript实现计算个人所得税
2015/05/10 Javascript
jQuery四种选择器使用及示例
2016/06/05 Javascript
AngularJS实用开发技巧(推荐)
2016/07/13 Javascript
BootStrap 模态框实现刷新网页并关闭功能
2017/01/04 Javascript
详解vue.js的事件处理器v-on:click
2017/06/27 Javascript
Angular 2 ngForm中的ngModel、[ngModel]和[(ngModel)]的写法
2017/06/29 Javascript
Angularjs上传文件组件flowjs功能
2017/08/07 Javascript
AngularJs 终极购物车(实例讲解)
2017/11/08 Javascript
vue3.0 CLI - 2.6 - 组件的复用入门教程
2018/09/14 Javascript
JavaScript静态作用域和动态作用域实例详解
2019/06/17 Javascript
js+canvas实现转盘效果(两个版本)
2020/09/13 Javascript
react ant Design手动设置表单的值操作
2020/10/31 Javascript
jQuery实现全选按钮
2021/01/01 jQuery
在Python的循环体中使用else语句的方法
2015/03/30 Python
Python实现将目录中TXT合并成一个大TXT文件的方法
2015/07/15 Python
举例讲解Python设计模式编程中的访问者与观察者模式
2016/01/26 Python
Python获取当前公网ip并自动断开宽带连接实例代码
2018/01/12 Python
python让列表倒序输出的实例
2018/06/25 Python
Django Admin 上传文件到七牛云的示例代码
2020/06/20 Python
Python 串口通信的实现
2020/09/29 Python
pandas处理csv文件的方法步骤
2020/10/16 Python
突袭HTML5之Javascript API扩展2—地理信息服务及地理位置API学习
2013/01/31 HTML / CSS
德国鞋子网上商店:Omoda.de
2017/03/31 全球购物
法国发饰品牌:Alexandre De Paris
2018/12/04 全球购物
毕业生求职简历的自我评价
2013/10/23 职场文书
法律专业实习鉴定
2013/12/22 职场文书
班级口号大全
2014/06/09 职场文书
售后前台接待岗位职责
2015/04/03 职场文书
Django使用redis配置缓存的方法
2021/06/01 Redis