与python列表混淆:它们还是不是迭代器?

Nli*_*tis 71 python iterator list

在Nutshell中研究Alex Marteli的Python,书中暗示任何具有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()
Run Code Online (Sandbox Code Playgroud)

但结果如下:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
AttributeError: 'list' object has no attribute 'next'
Run Code Online (Sandbox Code Playgroud)

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

所以当我再次尝试时,这一次略有不同,尝试这样做:

>>> _temp_iter = next(x)
Run Code Online (Sandbox Code Playgroud)

我收到了这个错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator
Run Code Online (Sandbox Code Playgroud)

但是如何列表不是迭代器,因为它似乎支持这个接口,并且当然可以在以下上下文中用作一个:

>>> for number in x:
...     print x
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我在脑海中澄清这一点吗?

Ign*_*ams 94

它们是可迭代的,但它们不是迭代器.可以传递iter()它们以隐式(例如,通过for)或显式地为它们获取迭代器,但它们本身不是迭代器.

  • @delnan我想你的意思是"他们的`iter`简单地回归'self`". (12认同)
  • 请注意,所有迭代器(表现良好)也是可迭代的 - 它们的`next`只返回`self`,所以你可以调用`iter(iter(iter(iter(x)))`并得到同样的东西作为`iter(x)`.这就是为什么`for`适用于没有类型嗅探的迭代和迭代器(好吧,无视性能优化). (10认同)
  • @gerrit:因为迭代器不支持随机访问。 (3认同)
  • 当然,下一个问题是;*为什么*它们不被设计为迭代器? (2认同)

Ash*_*ary 24

您需要首先使用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
Run Code Online (Sandbox Code Playgroud)

检查对象是否是迭代器:

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
Run Code Online (Sandbox Code Playgroud)


Vic*_*ent 20

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

  • __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
Run Code Online (Sandbox Code Playgroud)

如果将列表转换为迭代器:

>>> il = l.__iter__()  # equivalent to iter(l)
>>> for i in il:
...     print i,
 1 2 3 4
>>> for i in il:
...     print i,
>>> 
Run Code Online (Sandbox Code Playgroud)


小智 6

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

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

现在it包含迭代器对象,在引发StopIteration异常之前x,可以使用该对象it.next()

  • 导致…`AttributeError:'list'对象没有属性'iter'` (3认同)