>>> lst_iter = iter([1,2,3]) >>> lst_iter.__next__() 1 >>> lst_iter.__next__() 2 >>> lst_iter.__next__() 3 >>> lst_iter.__next__() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
这里注意:这里的__next__()方法和内置函数next(iterator, default=None)不是一个东西;(内置函数next(iterator, default=None)也可以返回迭代器的下一个值)
c) 而for循环可以捕获StopIteration异常并结束循环;
总结一下:
a)for....in iterable,会通过调用iter(iterable)函数(实际上,首先调用的对象的__iter__()方法),返回一个迭代器iterator;
b)每次循环,调用一次对象的__next__(self),直到最后一个值,再次调用会触发StopIteration
c)for循环捕捉到StopIteration,从而结束循环
上面说了这么多,到底什么是迭代器Iterator呢?
任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值;
既然知道了什么迭代器,那我们自定义一个迭代器玩玩:
1 class Iterator_test(object): 2 def __init__(self, data): 3 self.data = data 4 self.index = len(data) 5 6 def __iter__(self): 7 return self 8 9 def __next__(self): 10 if self.index <= 0 : 11 raise StopIteration 12 self.index -= 1 13 return self.data[self.index] 14 15 iterator_winter = Iterator_test('abcde') 16 17 for item in iterator_winter: 18 print(item)
View Code如何判断一个对象是一个迭代器对象呢?两个方法:
1)通过内置函数next(iterator, default=None),可以看到next的第一个参数必须是迭代器;所以迭代器也可以认为是可以被next()函数调用的对象
2)通过collection中的Iterator类型判断
>>> from collections import Iterator >>> >>> isinstance([1,2,3], Iterator) False >>> isinstance(iter([1,2,3]), Iterator) True >>> isinstance([1,2,3].__iter__(), Iterator) True >>>
这里大家会不会有个疑问:
对于迭代器而言,看上去作用的不就是__next__方法嘛,__iter__好像没什么卵用,干嘛还需要__iter__方法呢?
我们知道,python中迭代是通过for循环实现的,而for循环的循环对象必须是一个可迭代对象Iterable,而Iterable必须是一个实现了__iter__方法的对象;知道为什么需要__iter__魔术方法了吧;
那么我就是想自定义一个没有实现__iter__方法的迭代器可以吗?可以,像下面这样:
class Iterable_test(object): def __init__(self, data): self.data = data def __iter__(self): return Iterator_test(self.data) class Iterator_test(object): def __init__(self, data): self.data = data self.index = len(data) def __next__(self): if self.index <= 0 : raise StopIteration self.index -= 1 return self.data[self.index] iterator_winter = Iterable_test('abcde') for item in iterator_winter: print(item)
View Code