Python-for循环的内部机制
作者:monte 发布时间:2023-02-02 20:47:18
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
即可。
来源:https://segmentfault.com/a/1190000022911784


猜你喜欢
- 本文实例讲述了Python面向对象程序设计之私有变量,私有方法原理与用法。分享给大家供大家参考,具体如下:私有变量,私有方法:python的
- 实例076:做函数题目:编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+.
- 问题你想读写一个二进制数组的结构化数据到Python元组中。解决方案可以使用 struct 模块处理二进制数据。 下面是一段示例代码将一个P
- 今天有一位同学给了我一个excel文件,要求读取某些行,某些列,然后我试着做了一个demo,这里分享出来,希望能帮到大家:首先安装xlrd:
- 本文实例讲述了Python中DJANGO简单测试的用法。分享给大家供大家参考。具体如下:这里以facebook台湾的测试版为例。仅仅测试用户
- 备份MySQL数据库的命令mysqldump -hhostname -uusername -ppassword databasename &
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了
- parquet数据:列式存储结构,由Twitter和Cloudera合作开发,相比于行式存储,其特点是:可以跳过不符合条件的数据,只读取需要
- 本文实例为大家分享了asp.net存储和读取数据库图片的具体代码,供大家参考,具体内容如下1. 创建asp.net web窗体项目代码如下:
- 1、可以使用"+"号完成操作输出为:[1, 2, 3, 8, 'google', 'com
- 基本概述我们知道MySQL有2种方式指定复制同步的方式,分别为:基于binlog文件名及位点的指定方式 - 匿名事
- 本文实例为大家分享了python人民币大小写转换的具体代码,供大家参考,具体内容如下大家应该都知道,银行打印账单有时候会跟上人民币的阿拉伯数
- Python批量替换文件内容,支持嵌套文件夹import ospath="./"for root,dirs,files
- settings文件中配置:LOGGING = { 'version':1, 'disabl
- 利用go语言的协程并发优势爬取网页速度相当之快,博客园100页新闻标题只需一秒即可全部爬取package mainimport ( &quo
- 看下面的例子就明白了class Test(object): def __init__(self, value='hell
- 【OpenCV】⚠️高手勿入! 半小时学会基本操作 ⚠️ 圆圈检测概述OpenCV 是一个跨平台的计算机视觉库, 支持多语言, 功能强大.
- 有史以来最牛逼的绘图工具,没有之一plotly是现代平台的敏捷商业智能和数据科学库,它作为一款开源的绘图库,可以应用于Python、R、MA
- 用df命令查了下,果然磁盘满了,因为当时分区采用系统默认,不知道为什么不能自动扩容!以后在处理这个问题!如图所示:[root@snsgou
- matplotlib是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图。而且也