python——什么是迭代协议、迭代对象和迭代器?

什么是迭代协议

只要某个类型(类)定义了__iter__()__next__()方法就表示支持迭代协议。

__iter__()需要返回一个可迭代对象。只要定义了__iter__()就表示能够通过for/in/map/zip等迭代工具进行对应的迭代,也可以手动去执行迭代操作

1 for x in Iterator
2 X in Iterator

同时,可迭代对象还可以作为某些函数参数,例如将可迭代对象构建成一个列表list(Iterator)来查看这个可迭代对象会返回哪些数据:

L = list(Iterator)

需要注意的是,for/in/map/zip等迭代工具要操作的对象并不一定要实现__iter__(),实现了__getitem__()也可以。__getitem__()是数值索引迭代的方式,它的优先级低于__iter__()

__next__()方法用于向前一次返回一个结果,并且在前进到结尾的地方触发StopIteration异常。

再次说明,只要实现了这两个方法的类型,就表示支持迭代协议,可以被迭代。

例如open()的文件类型:

1 >>> f=open('a.txt')

2 >>> dir(f)

3 [... '__iter__', ... '__next__', ...]

但如果看下列表类型、元组、字符串等容器类型的属性列表,会发现没有它们只有__iter__(),并没有__next__()

1 >>> dir(list)
2 [... '__iter__', ...]
3
4 >>> dir(tuple)
5 [... '__iter__', ...]
6
7 >>> dir(str)
8 [... '__iter__', ...']
9 
10 >>> dir(set)
11 [... '__iter__', ...]
12
13 >>> dir(dict)
14 [... '__iter__', ...]

我是一名python开发工程师,整理了一套python的学习资料,从基础的python脚本到web开发、爬虫、
数据分析、数据可视化、机器学习、面试真题等。想要的可以进群:688244617免费领取

但为什么它们能进行迭代呢?继续看下文"可迭代对象"的解释。

 

什么是迭代对象和迭代器

对于前面的容器类型(list/set/str/tuple/dict)只有__iter__()而没有__next__(),但却可以进行迭代操作的原因,是这些容器类型的__iter__()返回了一个可迭代对象,而这些可迭代对象才是真的支持迭代协议、可进行迭代的对象。

1 >>> L=[1,2,3,4]
2 >>> L_iter = L.__iter__()
3 
4 >>> L_iter
5 <list_iterator object at 0x000001E53A105400>
6 
7 >>> dir(L_iter)
8 [... '__iter__', ... '__next__', ...]
9 
10 >>> L.__next__()
11 Traceback (most recent call last):
12   File "<stdin>", line 1, in <module>
13 AttributeError: 'list' object has no attribute '__next__'
14 
15 >>> L_iter.__next__()
16 1
17 >>> L_iter.__next__()
18 2
19 >>> L_iter.__next__()
20 3
21 >>> L_iter.__next__()
22 4

所以,对于容器类型,它们是通过__iter__()来返回一个迭代对象,然后这个可迭代对象需要支持迭代协议(有__iter__()__next__()方法)。

也就是说,所谓的迭代对象是通过__iter__()来返回的。迭代对象不一定可迭代,只有支持迭代协议的迭代对象才能称为可迭代对象

迭代器则是迭代对象的一种类型统称,只要是可迭代对象,都可以称为迭代器。所以,一般来说,迭代器和可迭代对象是可以混用的概念。但严格点定义,迭代对象是iter()返回的,迭代器是__iter__()返回的,所以它们的关系是:从迭代对象中获取迭代器(可迭代对象)。

如果要自己定义迭代对象类型,不仅需要返回可迭代对象,还需要这个可迭代对象同时实现了__iter__()__next__()

正如open()返回的类型,它有__iter__()和__next__(),所以它支持迭代协议,可以被迭代。再者,它的__iter__()返回的是自身,而自身又实现了这两个方法,所以它是可迭代对象:

1 >>> f = open('a.txt')
2 >>> f.__iter__() is f
3 True

所以,如果想要知道某个对象是否可迭代,可以直接调用iter()来测试,如果它不抛出异常,则说明可迭代(尽管还要求实现__next__())。

觉得文章还不错的话不妨点个赞,有任何建议或看法欢迎大家在评论区分享讨论!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值