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下用于监视文件系统的pyinotify包
Nov 13 Python
python脚本设置超时机制系统时间的方法
Feb 21 Python
Python文件夹与文件的相关操作(推荐)
Jul 25 Python
Python实现查找匹配项作处理后再替换回去的方法
Jun 10 Python
go和python变量赋值遇到的一个问题
Aug 31 Python
python生成requirements.txt的两种方法
Sep 18 Python
使用python客户端访问impala的操作方式
Mar 28 Python
离线状态下在jupyter notebook中使用plotly实例
Apr 24 Python
Python3实现英文字母转换哥特式字体实例代码
Sep 01 Python
python本地文件服务器实例教程
May 02 Python
Pandas数据类型之category的用法
Jun 28 Python
python脚本框架webpy模板赋值实现
Nov 20 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加密解密函数代码
2013/06/19 PHP
php实现给图片加灰色半透明效果的方法
2014/10/20 PHP
PHP 7.1新特性的汇总介绍
2016/12/16 PHP
PHP实现对数字分隔加千分号的方法
2019/03/18 PHP
PHP实现的62进制转10进制,10进制转62进制函数示例
2019/06/06 PHP
利用javascript查看html源文件
2006/11/08 Javascript
12个非常有创意的JavaScript小游戏
2010/03/18 Javascript
优化Node.js Web应用运行速度的10个技巧
2014/09/03 Javascript
浅谈Javascript中深复制
2014/12/01 Javascript
JavaScript里四舍五入函数round用法实例
2015/04/06 Javascript
JS中生成随机数的用法及相关函数
2016/01/09 Javascript
js Canvas实现圆形时钟教程
2016/09/19 Javascript
bootstrap中使用google prettify让代码高亮的方法
2016/10/21 Javascript
AngularJS入门教程之数据绑定原理详解
2016/11/02 Javascript
实例详解display:none与visible:hidden的区别
2017/03/30 Javascript
判断div滑动到底部的scroll实例代码
2017/11/15 Javascript
Angularjs Promise实例详解
2018/03/15 Javascript
微信小程序实现的一键拨号功能示例
2019/04/24 Javascript
layui 上传图片 返回图片地址的方法
2019/09/26 Javascript
webpack HappyPack实战详解
2019/10/08 Javascript
原生JS运动实现轮播图
2021/01/02 Javascript
[02:28]DOTA2英雄基础教程 灰烬之灵
2013/12/19 DOTA
对python numpy数组中冒号的使用方法详解
2018/04/17 Python
Django开发的简易留言板案例详解
2018/12/04 Python
python 直接赋值和copy的区别详解
2019/08/07 Python
Python实现线性插值和三次样条插值的示例代码
2019/11/13 Python
Python高阶函数、常用内置函数用法实例分析
2019/12/26 Python
Python实现数字的格式化输出
2020/08/01 Python
Django URL参数Template反向解析
2020/11/24 Python
详解Python中string模块除去Str还剩下什么
2020/11/30 Python
Django中如何用xlwt生成表格的方法步骤
2021/01/31 Python
新加坡鲜花速递/新加坡网上花店:Ferns N Petals
2020/08/29 全球购物
老师自我鉴定范文
2013/12/25 职场文书
个人安全生产承诺书
2014/05/22 职场文书
法定代表人证明书
2014/11/28 职场文书
【海涛解说】pis亲自推荐,其实你从来不会玩NW
2022/04/01 DOTA