85

我正在研究Alex Marteli 的 Python in a Nutshell,这本书建议任何具有next()方法的对象都是(或至少可以用作)迭代器。它还表明大多数迭代器是通过隐式或显式调用调用的方法构建的iter

读完这本书后,我有一种尝试的冲动。我启动了一个 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'

在困惑中,我试图通过研究 x 对象的结构,dir(x)我注意到它有一个__iter__函数对象。所以我发现它可以用作迭代器,只要它支持那种类型的接口。

因此,当我再次尝试时,这次略有不同,尝试这样做:

>>> _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

有人可以帮我澄清一下吗?

4

5 回答 5

112

它们是可迭代的,但它们不是迭代器。可以将它们传递iter()给以隐式(例如 via )或显式地为它们获取迭代器for,但它们本身并不是迭代器。

于 2012-10-24T17:03:44.183 回答
27

您需要先使用以下方法将列表转换为迭代器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
于 2012-10-24T17:03:23.513 回答
26

以防万一您对可迭代对象和迭代器之间的区别感到困惑。迭代器是表示数据流的对象。它实现了迭代器协议:

  • __iter__方法
  • next方法

重复调用迭代器的 next() 方法会返回流中的连续项。当没有更多数据可用时,迭代器对象将被耗尽,并且对其 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,
>>> 
于 2012-10-24T17:44:34.953 回答
8

List 不是迭代器,但列表包含一个迭代器对象__iter__,因此当您尝试在任何列表上使用 for 循环时,for 循环调用__iter__方法并获取迭代器对象,然后它使用列表的 next() 方法。

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
it = x.__iter__()

现在it包含迭代器对象,在抛出 StopIteration 异常之前x,您可以使用它it.next()

于 2014-07-23T12:47:00.210 回答
0

关于 list 是一个可迭代但不是迭代器的问题已经有了很好的答案。在 python 版本 > 3.0 中,使用以下

a = [1, 2, 3]
b = iter(a)
b.__next__()
于 2021-05-26T08:23:11.610 回答