内置函数iter()如何将Python列表转换为迭代器?

7

我已经阅读了相关资料,其中说明Python迭代器必须同时具有__iter____next__方法,但可迭代对象仅需要__iter__方法。

我检查了一个列表,并发现它没有__next__方法。当使用iter()在其上进行操作时,它将变成一个迭代器。这是否意味着iter()会向列表中添加一个__next__方法以将其转换为迭代器?

如果是,这是如何发生的?


1
不错的总结:http://nvie.com/posts/iterators-vs-generators/ - mkrieger1
1个回答

6

iter 不会将列表转换为迭代器,它返回一个迭代器。它不会修改列表,并且列表当然没有 __next__ 方法。

>>> x = [1,2]
>>> it = iter(x)
>>> it
<list_iterator object at 0x101c021d0>
>>> x.__next__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__next__'
>>>

列表是可迭代对象(iterables),而不是迭代器(iterators)。它们实现了__iter__方法,因此它们是可迭代的:

>>> x.__iter__
<method-wrapper '__iter__' of list object at 0x101bcf248>

但不包括__next__,因此它们不是迭代器:
>>> next(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object is not an iterator

按照定义,迭代器本身是可迭代的,因为它们也实现了__iter__。考虑以下代码:

>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> it = iter(x)
>>> it
<list_iterator object at 0x101c02358>
>>> it.__iter__
<method-wrapper '__iter__' of list_iterator object at 0x101c02358>

大多数迭代器在使用iter时应该简单地返回自身:

>>> it2 = iter(it)
>>> it, it2
(<list_iterator object at 0x101c02358>, <list_iterator object at 0x101c02358>)
>>> it is it2
True
>>>

确实,这是迭代器协议的一个要求

“迭代器需要有一个返回迭代器对象本身的__iter__()方法,所以每个迭代器也都是可迭代的,并且可以在大多数接受其他可迭代对象的地方使用。”

请注意,它们是相同的迭代器

>>> next(it)
1
>>> next(it2)
2
>>> next(it)
3
>>> next(it)
4
>>> next(it2)
5
>>> list(it)
[6, 7, 8, 9]
>>> next(it2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

所以一个迭代器实现了__iter____next__,可迭代对象只是指它实现了__iter__。由__iter__返回的是一个迭代器,因此必须实现__next__

关键是,__next__ 方法在 iter 返回的对象上。 - Eevee
注意:所有迭代器都必须有一个__iter__实现,该实现返回迭代器对象本身,而不仅仅是“大多数”。这是迭代器协议的要求:“迭代器需要有一个返回迭代器对象本身的__iter __()方法,因此每个迭代器也是可迭代的,并且可以在其他可迭代接受的大多数地方使用。” Python的其他部分依赖于此; 一种规范和高效的鸭子类型方法来测试某些东西是否为迭代器是测试obj is iter(someobj) - ShadowRanger
@ShadowRanger 是的,你说得完全正确。当然,没有什么能阻止你去打破这个规则,但我肯定不建议这样做。我会进行更新以反映这一点。 - juanpa.arrivillaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接