>>> class A(): def __init__(self, lst): self.lst = lst def __iter__(self): print('A.__iter__()方法被调用') return B(self.lst) >>> class B(): def __init__(self, lst): self.lst = lst self.index = 0 def __iter__(self): print('B.__iter__()方法被调用') return self def __next__(self): try: print('B.__next__()方法被调用') value = self.lst[self.index] self.index += 1 return value except IndexError: raise StopIteration() >>> a = A([1, 2, 3]) >>> a1 = iter(a) A.__iter__()方法被调用 >>> next(a1) B.__next__()方法被调用 1 >>> next(a1) B.__next__()方法被调用 2 >>> next(a1) B.__next__()方法被调用 3 >>> next(a1) B.__next__()方法被调用 Traceback (most recent call last): File "<pyshell#78>", line 11, in __next__ value = self.lst[self.index] IndexError: list index out of range During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<pyshell#84>", line 1, in <module> next(a1) File "<pyshell#78>", line 15, in __next__ raise StopIteration() StopIteration
A类实例化出来的实例a只是可迭代对象,不是迭代器,调用iter()方法后,返回了一个B类的实例a1,每次对a1调用next()方法,都用调用B类的__next__()方法。
接下来,我们用for循环遍历一下A类实例:
>>> for i in A([1, 2, 3]): print('for循环中取出值:',i) A.__iter__()方法被调用 B.__next__()方法被调用 for循环中取出值: 1 B.__next__()方法被调用 for循环中取出值: 2 B.__next__()方法被调用 for循环中取出值: 3 B.__next__()方法被调用
通过for循环对一个可迭代对象进行迭代时,for循环内部机制会自动通过调用iter()方法执行可迭代对象内部定义的__iter__()方法来获取一个迭代器,然后一次又一次得迭代过程中通过调用next()方法执行迭代器内部定义的__next__()方法获取下一个元素,当没有下一个元素时,for循环自动捕获并处理StopIteration异常。如果你还没明白,请看下面用while循环实现for循环功能,整个过程、原理都是一样的:
>>> a = A([1, 2, 3]) >>> a1 = iter(a) A.__iter__()方法被调用 >>> while True: try: i = next(a1) print('for循环中取出值:', i) except StopIteration: break B.__next__()方法被调用 for循环中取出值: 1 B.__next__()方法被调用 for循环中取出值: 2 B.__next__()方法被调用 for循环中取出值: 3 B.__next__()方法被调用 作为一个迭代器,B类对象也可以通过for循环来迭代: >>> for i in B([1, 2, 3]): print('for循环中取出值:',i) B.__iter__()方法被调用 B.__next__()方法被调用 for循环中取出值: 1 B.__next__()方法被调用 for循环中取出值: 2 B.__next__()方法被调用 for循环中取出值: 3 B.__next__()方法被调用 看出来了吗?这就是for循环的本质。
3 生成器 3.1 迭代器与生成器