今天准备写一写在学习python过程中,自己对于迭代器、迭代器协议以及可迭代对象之间的关系及自己的理解。可能有些不对的地方,欢迎大家及时指正。
可迭代对象
可迭代对象泛指一类对象,不是指的每一种对象,确切的说满足以下的条件的对象可以成为可迭代对象:
- 对象实现了
__iter__
方法 __iter__
方法返回了一个迭代器对象
我们比较容易理解的可迭代对象,比如说可以用for
语句去遍历,实际for语句的内部实现应该就是首先调用对象的__iter__
方法,获取一个迭代器对象,接着不停的调用迭代器对象的__next__
方法,循环遍历取值。
迭代器对象(迭代器)
在可迭代对象我们提到了迭代器对象,什么是迭代器对象?同样这里泛指一类满足一些条件的一类对象,就可以称之为迭代器对象。也就是满足迭代器协议的一类对象。
协议: 我个人理解是对一系列条件的描述。
迭代器协议包括这些条件:
- 对象实现了
__next__
方法 __next__
方法返回了某个数值(当然一般情况下,我们需要的是返回这个对象的特定的数字,并且按照一定的顺序进行依次返回)__next__
方法需要在值取完的时候,抛出StopIteration
的错误信息。
总结:
- 可迭代对象是 调用对象的
__iter__
方法能够返回迭代器对象的一种对象。 - 迭代器对象是实现了迭代器协议的对象。
那么有没有一种情况,就是一个对象本身自己就是迭代器对象,同时__iter__
方法返回自己,这样自己就满足了可迭代对象,迭代器对象的两重要求。
实际上,大部分内建的容器对象,例如字典、列表等,都是这样实现的,他们对象本身就是迭代器对象。
我们通过一个自己写一个可迭代对象,来让大家更深入的了解。
比如:
for i in range(1,10,1):
...
这个大家应该不陌生,实际上range(1,10,1)生成的就是一个可迭代对象,遍历它会一次获取1 - 9 的自然数,我们就自己实现一个MyRange类,达到同样的效果。
class MyRange:
def __init__(self,start_index,end_index,step):
# 这里为了简化,我们就不考虑默认值的情况了,要让用户必须输入起始数值和步长,也不考虑步长为负数的时候反向取值了,默认只能输入正数。
self.start_index = start_index
self.end_index = end_index
self.step = step
def __iter__(self):
# 接下来,我们就来实现可迭代对象的一个性质,返回迭代器对象,这里我们返回了一个M\yRangeIteration对象,同时用起始值和步长对,迭代器对象进行初始化,接下来我们会来定义这个迭代器对象.
return MyRangeIteration(self.start_index,self.end_index,self.step)
class MyRangeIteration:
def __init__(self,start,end,step):
self.start = start
self.end = end
self.step = step
def __next__(self):
# 迭代器对象的要求是实现迭代器协议,1.实现了__next__方法,
if self.start < self.end :
result = self.start
# 以step步距调整self.start的值,为下一次的调用做准备。
self.start += self.step
# 2. 返回一个值
return result
else:
# 3. 没有值可以取了,抛出异常StopIteration
raise StopIteration
if __name__ == '__main__':
for i in MyRange(1,10,1):
print(i)
我们得到以下结果:
1
2
3
4
5
6
7
8
9
[Finished in 0.3s]
这样我们通过一个简单的实例,了解了可迭代对象和迭代器对象这几个概念之间的差别和联系。在我学习的时候,反正自己是花了很长一段时间,才算弄清楚。
希望以上的东西,能够帮到初学者,同时也欢迎大家对不足的地方进行指正。