如果一个对象实现了__iter__方法,那么就是可迭代的Iterable
Python的collections模块提供了Iterable和Iterator这两个抽象类,可以让我们检测一个对象是否是可迭代的以及是否是迭代器
In [16]: class MyIterable(object):
...: def __iter__(self):
...: return None
...:
In [17]: myiter = MyIterable()
In [18]: isinstance(myiter, Iterable)
Out[18]: True
我们经常用for来遍历一些对象例如list、tuple和file,这种遍历即为迭代,那这些对象也即是可迭代对象。
总言之,能被for遍历的对象都是可迭代对象,但是可迭代对象不一定能被for遍历,有点绕。
In [22]: for i in myiter:
...: print(i)
...:
------------------------------------------------------------
TypeError Traceback (most re
in ()
----> 1 for i in myiter:
2 print(i)
3
TypeError: iter() returned non-iterator of type 'NoneType'
如上所示,我们自定义的MyIter类的实例无法被for遍历,究其原因,就是for在遍历一个对象时,需要先用内置函数iter将该对象转换为一个迭代器,然后才能进行遍历;而我们上述的MyIter类的__iter__方法返回的却是一个None。
说到迭代器,就要讲下迭代器协议: 对于一个对象,使用next方法来调用它,要么返回迭代的下一项,要么返回一个StopIteration异常表示迭代终止。
迭代器就是实现了迭代器协议的对象,也即实现了__next__方法(python2中是next方法),经过测试发现,只实现__next__方法还是不够的。
In [25]: class MyIterator(object):
...:
...: def __next__(self):
...: return 1
...:
In [26]: myiterator = MyIterator()
In [27]: isinstance(myiterator, Iterator)
Out[27]: False
还需要实现__iter__方法才行。
In [31]: class MyIterator(object):
...:
...: def __iter__(self):
...: return self
...:
...: def __next__(self):
...: return 1
...:
In [32]: myiterator = MyIterator()
In [33]: isinstance(myiterator, Iterator)
Out[33]: True
所以,我得出一个新的结论: 迭代器必是可迭代对象, 反之不成立。