1、迭代器介绍
迭代器即用来迭代取值的工具,而迭代是重复反馈过程的活动。其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代
1 2 3 4 5 6 | goods = [ 'mac' , 'lenovo' , 'acer' , 'dell' , 'sony' ] index = 0 while index < len (goods): print (goods[index]) index + = 1 |
上述while循环才是一个迭代过程,不仅满足重复,而且以每次重新赋值后的index值作为下一次循环中新的索引进行取值,反复迭代,最终可以取尽列表中的值
注意:
- 上面这个迭代方法只适合序列类型,并不适合字典、集合、文件对象的迭代取值。
- 有人会说for循环可以对字典、文件对象、集合进行循环取值,其实for循环用到的是迭代器,因此这里没有用for循环为例说明,后面会具体说迭代器和可迭代对象的区别与联系
(1)可迭代对象
通过索引的方式进行迭代取值,实现简单,但仅适用于序列类型:字符串,列表,元组。对于没有索引的字典、集合、文件对象等非序列类型,必须找到一种不依赖索引来进行迭代取值的方式,这就用到了迭代器。
可迭代对象(Iterable)。从语法形式上讲,内置有__iter__方法的对象都是可迭代对象,字符串、列表、元组、字典、集合、打开的文件都是可迭代对象。
1 2 3 | { 'name' : 'amy' }.__iter__ { 7 , 8 , 9 }.__iter__ …… |
重点:
1 2 | 像我们 range 返回的就是一个优化了的可迭代对象,为什么叫优化了的? 因为普通的可迭代对象就像python2中的 range , 返回的是个列表, [ 1 , 2 , 3 , 4 ], 可以通过索引取值 |
(2)迭代器对象
调用obj.iter()方法返回的结果就是一个迭代器对象(Iterator)。
除文件对象外,字典、集合、列表等都只是可迭代对象而已,它们可以通过调用iter方法生成迭代器对象,并进行迭代取值。但文件对象在python中使用时,直接生成的就是迭代器对象,当然它也是可迭代对象。文件对象可以直接调用next函数,只有迭代器对象才能调用next方法,因此文件对象是迭代器对象。执行迭代器对象.iter()方法得到的仍然是迭代器本身,而执行迭代器对象.next()方法就会计算出迭代器中的下一个值。
1 2 3 4 5 6 7 8 9 | >>> s = { 1 , 2 , 3 } # 可迭代对象s >>> i = iter (s) # 本质就是在调用s.__iter__(),返回s的迭代器对象i, >>> next (i) # 本质就是在调用i.__next__() 1 >>> next (i) 2 >>> next (i) 3 >>> next (i) #抛出StopIteration的异常,代表无值可取,迭代结束,要想继续取值,除非再重新生成一个迭代器。 |
为什么文件对象要直接设置成迭代器对象,集合、字典等不设置成迭代器对象呢?
1 2 | 答:首先我们应该明白迭代器这种需要一个值, next 方法取一个值,这样是降低了内存的消耗的。 集合、字典等定义下来,本来就不是用来存很多、很多东西的。但是一个文件对象却可以很大很大,因此必须直接生成迭代器对象,控制内存的消耗。 |
2、for循环原理
有了迭代器后,我们便可以不依赖索引迭代取值了,使用while循环的实现方式如下
1 2 3 4 5 6 7 | dic = { 'a' : 1 , 'b' : 2 , 'c' : 3 } d_iterator = iter (dic) #d_iterator便是一个迭代器对象,iter方法生成的就是一个迭代器对象 while True : # while循环的循环体是进行循环迭代取值的 try : print ( next (d_iterator)) except (StopIteration): # 捕获异常 break # 异常处理 |
for循环又称为迭代循环,in后可以跟任意可迭代对象,上述while循环可以简写为:
1 2 3 | dic = { 'a' : 1 , 'b' : 2 , 'c' : 3 } for i in dic: print (i) |
for 循环在工作时,首先会调用可迭代对象dic内置的iter方法拿到一个迭代器对象,然后再调用该迭代器对象的next方法将取到的值赋给i,执行循环体完成一次循环,周而复始,直到捕捉StopIteration异常,结束迭代。
为什么文件对象中也需要有iter方法呢?
它不是已经是迭代器对象了吗,而且前面说迭代器调用iter方法屁用没有,得到的还是本身。
1 2 | 答:这是一个专门为统一 for 循环而设计的,因为 for 循环中你不确定自己 in 后面到底是不是迭代器对象,难道还要判断一下吗? 那不是太麻烦了,无论谁来,只要可迭代,我就给你 iter 方法一下,即使是文件对象,也不影响啥。所以文件对象也需要一个 iter 方法,拿去让 for 循环调用。 |
3、迭代器的优缺点
基于索引的迭代取值,所有迭代的状态(迭代的位置信息)都保存在了索引中,而基于迭代器实现迭代的方式不再需要索引,所有迭代的状态就保存在迭代器中,然而这种处理方式优点与缺点并存:
(1)优点
为序列和非序列类型提供了一种统一的迭代取值方式。
惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。
(2)缺点
除非取尽,否则无法直接获取迭代器的长度
只能取下一个值,不能回到开始,更像是'一次性的',迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。
4、小结
字符串、列表、元组、字典、集合、打开的文件都是可迭代对象。其中字符串、列表、元组是序列类型,可以基于索引迭代取值。
迭代器对象 = iter(可迭代对象)
next(迭代器对象)
————————————————
版权声明:本文为CSDN博主「凤求凰的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44571270/article/details/106005998
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!