与Python列表混淆:他们还是不是迭代器?
我正在研究Alex Marteli的Python in the Nutshell ,本书指出任何具有next()
方法的对象都是(或者至less可以用作) 迭代器 。 它也表明大多数迭代器是通过对称为iter
的方法的隐式或显式调用来构build的。
在读完这本书之后,我觉得有尝试的冲动。 我启动了一个Python 2.7.3解释器,并做到了这一点:
>>> x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> for number in range(0, 10): ... print x.next()
但结果是这样的:
Traceback (most recent call last): File "<stdin>", line 2, in <module> AttributeError: 'list' object has no attribute 'next'
在困惑中,我试图通过dir(x)
来研究x对象的结构,我注意到它有一个__iter__
函数对象。 所以我发现它可以用作迭代器,只要它支持这种types的接口。
所以当我再次尝试时,这次稍微不同,试图做到这一点:
>>> _temp_iter = next(x)
我得到这个错误:
Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: list object is not an iterator
但是一个列表如何不能成为一个迭代器,因为它似乎支持这个接口,并且在下面的上下文中当然可以用作一个:
>>> for number in x: ... print x
有人能帮我澄清一下吗?
它们是可迭代的 ,但它们不是迭代器 。 他们可以被传递给iter()
以隐式地(例如通过for
)或者显式地获得它们的迭代器,但是它们本身并不是迭代器。
您需要先使用iter()
将列表转换为迭代器:
In [7]: x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In [8]: it=iter(x) In [9]: for i in range(10): it.next() ....: ....: Out[10]: 0 Out[10]: 1 Out[10]: 2 Out[10]: 3 Out[10]: 4 Out[10]: 5 Out[10]: 6 Out[10]: 7 Out[10]: 8 Out[10]: 9 In [12]: 'next' in dir(it) Out[12]: True In [13]: 'next' in dir(x) Out[13]: False
检查对象是否是迭代器:
In [17]: isinstance(x,collections.Iterator) Out[17]: False In [18]: isinstance(x,collections.Iterable) Out[18]: True In [19]: isinstance(it,collections.Iterable) Out[19]: True In [20]: isinstance(it,collections.Iterator) Out[20]: True
以防万一您对迭代器和迭代器之间的差异感到困惑。 迭代器是表示数据stream的对象。 它实现了迭代器协议:
-
__iter__
方法 -
next
方法
重复调用迭代器的next()方法返回stream中的连续项。 当没有更多的数据可用时,迭代器对象将耗尽,并且对next()方法的任何进一步调用只会再次引发StopIteration。
另一方面,可迭代对象实现__iter__
方法,当被调用时返回一个迭代器,允许多次传递数据。 可重用对象是可重用的,一旦耗尽,可以重复使用。 它们可以使用iter
函数转换为迭代器。
所以如果你有一个列表(可迭代),你可以这样做:
>>> l = [1,2,3,4] >>> for i in l: ... print i, 1 2 3 4 >>> for i in l: ... print i, 1 2 3 4
如果你把你的列表转换成一个迭代器:
>>> il = l.__iter__() # equivalent to iter(l) >>> for i in il: ... print i, 1 2 3 4 >>> for i in il: ... print i, >>>
List不是迭代器,但列表包含一个迭代器对象__iter__
所以当你尝试在任何列表上使用for循环,for循环调用__iter__
方法并获取迭代器对象,然后使用列表的next()方法。
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] it = x.__iter__()
现在it
包含x
迭代器对象,您可以使用它作为it.next()
直到引发StopIterationexception