1. 迭代器简介
1.1 什么是迭代器
看过装饰器之后,大家都知道了器就是工具,装饰器是用来装饰的工具,迭代器就是用来迭代的工具
那什么是迭代呢? 迭代一般都是用来取值的 , 所以
# 迭代器指的是迭代取值的工具,迭代是一个重复的过程,
# 每次重复都是基于上一次的结果而继续的,两次重复是有关系的,单纯的重复并不是迭代
1.2 为什么要有迭代器
既然迭代器是迭代取值,而涉及到把多个值取出来的数据类型有 :
- 列表 字符串 元组 字典 集合 文件句柄 range( )对象
l = ['ymn', 'tom', 'jack']
i = 0
while i < len(l):
print(l[i])
i += 1
上述取值的方式确实是迭代取值,但是有一定的局限性,都是通过索引迭代取值的,但是我们知道有些数据类型是
没有索引的,没有办法通过索引取值,所以python必须提供一种能够不依赖索引的取值方式,所以有了迭代器
1.3 如何使用迭代器
如何使用迭代器的前提就是怎样才能创建一个迭代器?我们知道要用变量直接赋值一个,比如name = "ymn"
迭代器是通过可迭代对象转变而来的,意思就是说你要先有个可迭代器对象,然后通过某种方法可以把可迭代器
对象转化成迭代器,这个时候你肯定又迷了,tmd迭代器什么?可迭代对象又是什么?可迭代对象实际上我们
经常使用只是你不知道他还可以叫做可迭代对象而已
2. 可迭代对象
前提 : 在python中万物皆是对象,变量是对象,函数是对象等等等
在python中我们把具有__iter__
方法的对象都称之为可迭代对象,我们来看一下那些对象具有__iter__
方法
l = []
l.__iter__()
s = "ymn"
s.__iter__()
t = (1,)
t.__iter__()
d = {}
d.__iter__()
set1 = set()
set1.__iter__()
with opne('a.txt',mode="r",encoding="utf-8") as f:
f.__iter__() # 彩蛋
r = range(1,10)
r.__iter__()
我靠,tmd你发现以前学的好多都是可迭代对象。
3. 可迭代对象转化成迭代器
通过一个可迭代器对象转换为迭代器简直不要太简单,直接调用可迭代对象的__iter__
方法就能返回一个迭代器
l = ['ymn', 'tom', 'jack']
l_iterator = l.__iter__()
print(l_iterator) # <list_iterator object at 0x000002B271ADD518>
迭代器对象内置具有__next__
和__iter__
方法,通过方法可以从迭代器中取值
l = ['ymn', 'tom', 'jack']
l_iterator = l.__iter__()
print(l_iterator.__next__()) # ymn
print(l_iterator.__next__()) # tom
print(l_iterator.__next__()) # jack
print(l_iterator.__next__()) # 报错,因为迭代器里面的值已经取完了
强调 :迭代器中的值只能取一次,一旦取出来后就不在里面了,不是像列表,元组。
既然迭代器取值,只用__next__
方法就行了,为什么还要有__iter__
方法呢?我们来看一下__iter__
方法返
回什么
l = ['ymn', 'tom', 'jack']
l_iterator = l.__iter__()
print(l_iterator) # <list_iterator object at 0x000001B36963D518>
print(l_iterator.__iter__()) # <list_iterator object at 0x000001B36963D518>
发现迭代器调用__iter__
方法之后还是迭代器,那tmd要它何用,不如剁了,不急看完for循环的工作原理你就
知道了
4. for循环的工作原理
for循环取值实际上就是把可迭代对象转换为迭代器,然后调用__next__
方法,那为什么for循环就知道什么时候
取的是最后一个值呢?就能保证不报错呢?实际上for也不知道什么时候取的是最后一个值,只不过for循环内部做
了异常处理。
l = ['ymn', 'tom', 'jack']
l_iterator = l.__iter__()
while 1:
try: # 尝试执行
ret = l_iterator.__next__()
print(ret)
except StopIteration: # 捕获到异常退出循环
break
for x in l # 这句代码实际上内部做的就是上面那些操作
但是 : 如果in后面的对象本身就是一个迭代器呢?,如果他没有__iter__
方法,你就不能for循环了,既然是取
值,就应该让for循环也可以直接操作迭代器,于是python在迭代器中又内置了一个__iter__
方法,调用之后返回
返回自己实际上我们用的文件句柄就是迭代器,他具有__iter__
和__next__
两个方法
with opne('a.txt',mode="r",encoding="utf-8") as f:
f.__iter__()
f.__next__()
5. 迭代器的优缺点
优点
-
迭代器提供一种不依赖于索引的取值方式,这样可以遍历没有索引的可迭代对象
-
迭代器与列表比较,迭代器是进行惰性计算的,更省内存
缺点
- 无法获取迭代器长度,不如使用索引取值灵活
- 迭代器只能遍历一次,不能回退
- 必须依靠可迭代对象转换,可迭代器对象耗内存