for循环
1 for i ins:2 print(i)
在上述for循环中,不断地将s中的值赋值给i,然后打印出来。这种只针对s中元素的循环称为对s的迭代,能够迭代的s称为可迭代的。
python为了实现for循环,需要迭代的对象实现迭代协议或序列协议,以获取一个迭代器。下面只讨论迭代协议,即实现一个预定义的方法:
1 __iter__(self):返回一个迭代器
for在对对象进行迭代时,会调用对象的__iter__方法构造一个迭代器,然后对该迭代器进行迭代,迭代过程就是不断调用迭代器的方法获取元素:
1 __next__(self):返回下一个元素,迭代完成抛出stopIteration异常
定义上,实现了上述两个方法的对象称作迭代器。
从理论上讲__iter__方法只要返回一个包含__next__方法的对象就行了,不一定要是迭代器。
这里需要区分迭代器和可迭代对象,迭代器是实现了__iter__和__next__方法的对象,它一定是可迭代对象。而可迭代对象不一定是迭代器,实现了__iter__方法就是可迭代对象。
列表、元组、字符串、字典等对象只实现了__iter__方法,所以它们是可迭代对象,而不是迭代器。
列表不是迭代器
1 classA:2 def __iter__(self):3 return [1, 2, 3, 4, 5]4
5 classB:6 def __iter__(self):7 return [1, 2, 3, 4, 5].__iter__()8
9 try:10 for a inA():11 print(a)12 exceptException as e:13 print(e)14
15 for b inB():16 print(b)
输出结果
1 iter() returned non-iterator of type 'list'
2 1
3 2
4 3
5 4
6 5
__iter__方法一定要返回迭代器,而列表虽然是可迭代对象,但不是迭代器,所以会抛出异常。显式调用列表的__iter__方法返回一个迭代器即可正常运行。
__iter__返回的对象实现了__next__就可以正常迭代
1 classA:2 def __iter__(self):3 returnB()4
5 classB:6 def __init__(self):7 self.i =08 self.n = 5
9 def __next__(self):10 if self.i <11 self.i>
12 returnself.i13 raiseStopIteration14
15 for i inA():16 print(i)
输出结果
1 1
2 2
3 3
4 4
5 5
for循环对A的实例进行迭代,__iter__返回了B的实例,它没有__iter__方法,所以不是迭代器,但是可以正常迭代。
使用序列协议的for循环
1 classA:2 def __init__(self):3 self.array = [1, 2, 3, 4, 5]4
5 def __getitem__(self, i):6 returnself.array[i]7
8 for i inA():9 print(i)
输出结果
1 1
2 2
3 3
4 4
5 5
上述代码实现序号从0开始的__getitem__方法,即实现了序列协议,于是for循环能够从实现序列协议的对象中构造一个迭代器用于迭代。
for循环获取迭代器的本质是通过内建函数iter,它能够将实现了迭代器协议(主要是__iter__方法)或者序列协议(__getitem__,序号从0开始)的对象转换成生成器。在两种协议都存在的情况下,以迭代器协议为准。
总结:
1. 迭代器是实现了__iter__和__next__方法的对象,可迭代对象实现了__iter__或者实现了序列协议,可在for中进行迭代。列表等对象不是迭代器
2. for循环利用iter函数获取迭代器,之后对迭代器进行迭代
11>