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中的floor()方法
May 15 Python
Python找出list中最常出现元素的方法
Jun 14 Python
python用pickle模块实现“增删改查”的简易功能
Jun 07 Python
python实现比较文件内容异同
Jun 22 Python
Pandas分组与排序的实现
Jul 23 Python
python列表返回重复数据的下标
Feb 10 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
Feb 29 Python
基于Python快速处理PDF表格数据
Jun 03 Python
python读取hdfs并返回dataframe教程
Jun 05 Python
Python使用shutil模块实现文件拷贝
Jul 31 Python
如何利用python进行时间序列分析
Aug 04 Python
详解pycharm配置python解释器的问题
Oct 15 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中大括号作用介绍
2012/03/22 PHP
PHP中Laravel 关联查询返回错误id的解决方法
2017/04/01 PHP
php简单计算权重的方法示例【适合抽奖类应用】
2019/06/10 PHP
解决laravel-admin 自己新建页面里 js 需要刷新一次的问题
2019/10/03 PHP
jQuery EasyUI中对表格进行编辑的实现代码
2010/06/10 Javascript
读jQuery之十四 (触发事件核心方法)
2011/08/23 Javascript
jQuery(非HTML5)可编辑表格实现代码
2012/12/11 Javascript
a标签的href和onclick 的事件的区别介绍
2013/07/26 Javascript
js加密解密字符串可自定义密码因子
2014/05/13 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
JavaScript中的setMilliseconds()方法使用详解
2015/06/11 Javascript
jquery常用函数与方法汇总
2015/09/01 Javascript
Bootstrap页面布局基础知识全面解析
2016/06/13 Javascript
关于Node.js中Buffer的一些你可能不知道的用法
2017/03/28 Javascript
关于javascript作用域的常见面试题分享
2017/06/18 Javascript
vue 文件目录结构详解
2017/11/24 Javascript
JS实现的抛物线运动效果示例
2018/01/30 Javascript
vue3.0 CLI - 2.5 - 了解组件的三维
2018/09/14 Javascript
微信小程序websocket聊天室的实现示例代码
2019/02/12 Javascript
JavaScript数据结构与算法之基本排序算法定义与效率比较【冒泡、选择、插入排序】
2019/02/21 Javascript
NodeJS模块Buffer原理及使用方法解析
2020/11/11 NodeJs
通过Pandas读取大文件的实例
2018/06/07 Python
python pandas库中DataFrame对行和列的操作实例讲解
2018/06/09 Python
Python3中编码与解码之Unicode与bytes的讲解
2019/02/28 Python
Django组件cookie与session的具体使用
2019/06/05 Python
解决pycharm remote deployment 配置的问题
2019/06/27 Python
Pytorch中accuracy和loss的计算知识点总结
2019/09/10 Python
keras打印loss对权重的导数方式
2020/06/10 Python
用OpenCV进行年龄和性别检测的实现示例
2021/01/29 Python
几个解决兼容IE6\7\8不支持html5标签的几个方法
2013/01/07 HTML / CSS
如何减少垃圾回收让内存更加有效使用
2013/10/18 面试题
广告业务员岗位职责
2014/02/06 职场文书
彩色的翅膀教学反思
2014/04/25 职场文书
自我查摆剖析材料
2014/10/11 职场文书
迁户口计划生育证明
2014/10/19 职场文书
解决MySQL添加新用户-ERROR 1045 (28000)的问题
2022/03/03 MySQL