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中使用SAX解析xml实例
Nov 21 Python
粗略分析Python中的内存泄漏
Apr 23 Python
深入解析Python设计模式编程中建造者模式的使用
Mar 02 Python
Python错误: SyntaxError: Non-ASCII character解决办法
Jun 08 Python
pip安装Python库时遇到的问题及解决方法
Nov 23 Python
Python实现图片拼接的代码
Jul 02 Python
windows7 32、64位下python爬虫框架scrapy环境的搭建方法
Nov 29 Python
Python3 jupyter notebook 服务器搭建过程
Nov 30 Python
python实现抽奖小程序
Apr 15 Python
PyCharm搭建Spark开发环境实现第一个pyspark程序
Jun 13 Python
python3.7 利用函数os pandas利用excel对文件名进行归类
Sep 29 Python
Python如何把十进制数转换成ip地址
May 25 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
不用数据库的多用户文件自由上传投票系统(2)
2006/10/09 PHP
php给每个段落添加空格的方法
2015/03/20 PHP
Laravel 实现添加多语言提示信息
2019/10/25 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
js tab效果的实现代码
2009/12/26 Javascript
jQuery去掉字符串起始和结尾的空格(多种方法实现)
2013/04/01 Javascript
js 验证身份证信息有效性
2014/03/28 Javascript
jQuery学习笔记之jQuery.extend(),jQuery.fn.extend()分析
2014/06/09 Javascript
JavaScript面对国际化编程时的一些建议
2015/06/24 Javascript
js淡入淡出焦点图幻灯片效果代码分享
2015/09/08 Javascript
jquery分页插件jquery.pagination.js实现无刷新分页
2016/04/01 Javascript
js判断出两个字符串最大子串的函数实现方法
2016/11/01 Javascript
vue日期组件 支持vue1.0和2.0
2017/01/09 Javascript
JS实现京东首页之页面顶部、Logo和搜索框功能
2017/01/12 Javascript
原生js实现可拖动的登录框效果
2017/01/21 Javascript
jQuery插件FusionCharts绘制的2D帕累托图效果示例【附demo源码】
2017/03/28 jQuery
JavaScript运动框架 多物体任意值运动(三)
2017/05/17 Javascript
JavaScript简介_动力节点Java学院整理
2017/06/26 Javascript
vue+vux实现移动端文件上传样式
2017/07/28 Javascript
关于jquery form表单序列化的注意事项详解
2017/08/01 jQuery
Vue 解决通过this.$refs来获取DOM或者组件报错问题
2020/07/28 Javascript
插入排序_Python与PHP的实现版(推荐)
2017/05/11 Python
使用pytorch进行图像的顺序读取方法
2018/07/27 Python
利用python打开摄像头及颜色检测方法
2018/08/03 Python
python读取raw binary图片并提取统计信息的实例
2020/01/09 Python
Python random模块制作简易的四位数验证码
2020/02/01 Python
Windows下Sqlmap环境安装教程详解
2020/08/04 Python
HTML5自定义属性前缀data-及dataset的使用方法(html5 新特性)
2017/08/24 HTML / CSS
重阳节登山活动方案
2014/02/03 职场文书
丧事主持词大全
2014/04/02 职场文书
高三学生评语大全
2014/04/25 职场文书
化学专业自荐信
2014/05/28 职场文书
三峡大坝导游词
2015/01/31 职场文书
2015年环卫处个人工作总结
2015/07/27 职场文书
创业计划书之餐饮
2019/09/02 职场文书
创业计划书之面包店
2019/09/17 职场文书