第二模块第16章 迭代器
egon老师知乎文章:
https://zhuanlan.zhihu.com/p/109083551
1. 什么是迭代器
迭代器指的是迭代取值的工具
迭代是一个重复的过程, 每次重复都是基于上一次的结果而继续的, 单纯的重复并不是迭代.
2. 为何要有迭代器
迭代器是用来迭代取值的工具, 而涉及到把多个值循环取出来的类型有:
字符串, 列表, 元祖, 字典, 集合, 打开的文件对象
lst = ['a', 'b, 'c'] i = 0 while i < len(lst): print(l[i]) i += 1
但是, 上述迭代取值的方式只适用于有索引的数据类型: 列表, 字符串, 元祖
为了打破依靠索引迭代取值的局限性, python必须提供一种不依赖于索引取值的方式, 即迭代器.
3. 如何用迭代器
可迭代对象: 但凡内置有__iter__方法的都称为可迭代对象
示例:
print('__iter__' in dir(list)) # 结果:True print('__iter__' in dir(dict)) # 结果:True
lst = [1, 2, 3, 4, 5] i = lst.__iter__() # 调用可迭代对象下的__iter__方法会将其转换成迭代器对象, 然后调用__next__方法就可以取值 print(i) print(i.__next__()) # 结果: 1 print(i.__next__()) # 结果: 2 print(i.__next__()) # 结果: 3 print(i.__next__()) # 结果: 4 print(i.__next__()) # 结果: 5
对同一个迭代器取值, 如果取干净了, 再去取值则取不到, 如果想再取值, 则需要再造一次生成器.
4. 可迭代对象与迭代器对象详解
可迭代对象(可以转换成迭代器的对象): 内置有__iter__方法的对象
可迭代对象.__iter__(), 得到迭代器对象
迭代器对象: 内置有__next__方法并且内置有__iter__方法的对象
迭代器对象.__next__(), 得到迭代器的下一个值
迭代器对象.__iter__(), 得到的是迭代器本身, 调跟没调一个样,
那么迭代器对象存在__iter__方法的目的是统一for循环的工作方式,
即对于 'for i in 可迭代对象/迭代器对象:', 不管是可迭代对象还是迭代器对象, for循环调用的就是__iter__方法.
总结: 可迭代对象不一定是迭代器对象, 迭代器对象是可迭代对象,
字符串, 列表, 元祖, 字典, 集合中都无__next__方法, 是可迭代对象, 但是不是迭代器对象,
打开的文件对象有__next__方法, 是可迭代对象, 同时也是迭代器对象.
5. for循环的原理
for循环可以称为迭代/迭代器循环, 工作原理如下:
1. lst.__iter__()得到一个迭代器对象
2. 迭代器对象.__next__(), 拿到一个返回值, 将该返回值赋值给item
3. 循环往复步骤2, 直到抛出异常StopIteration, for循环会捕捉异常, 然后结束循环.
lst = [1, 2, 3, 4] i = lst.__iter__() while True: try: item = i.__next__() print(item) except StopIteration: break
注意: list('hello')原理同for循环
6. 迭代器优缺点总结
基于索引的迭代取值,所有迭代的状态都保存在了索引中,而基于迭代器实现迭代的方式不再需要索引,所有迭代的状态就保存在迭代器中,然而这种处理方式优点与缺点并存:
优点:
1、为序列和非序列类型提供了一种统一的迭代取值方式。
2、惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。
缺点:
1、除非取尽,否则无法获取迭代器的长度
2、只能取下一个值,不能回到开始,更像是‘一次性的’,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。
浙公网安备 33010602011771号