迭代器

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. 迭代器的优缺点

优点

  • 迭代器提供一种不依赖于索引的取值方式,这样可以遍历没有索引的可迭代对象

  • 迭代器与列表比较,迭代器是进行惰性计算的,更省内存

缺点

  • 无法获取迭代器长度,不如使用索引取值灵活
  • 迭代器只能遍历一次,不能回退
  • 必须依靠可迭代对象转换,可迭代器对象耗内存
原文地址:https://www.cnblogs.com/xcymn/p/14081660.html