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

Posted

技术标签:

【中文标题】内置函数 iter() 如何将 Python 列表转换为迭代器?【英文标题】:How does the built-in function iter() convert a Python list to an iterator? 【发布时间】:2018-01-09 13:10:26 【问题描述】:

我已经阅读了我的资料,其中指出 Python 迭代器必须同时具有 __iter____next__ 方法,但可迭代只需要 __iter__

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

如果是,这是怎么发生的?

【问题讨论】:

不错的总结:nvie.com/posts/iterators-vs-generators 【参考方案1】:

没有。 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
>>>

确实,这是requirement of the iterator protocol:

"迭代器必须有一个__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

所以iterator实现了__iter____next__iterable仅仅意味着它实现了__iter____iter__返回的是一个迭代器,所以它必须实现__next__

【讨论】:

至关重要的是,__next__ 方法是iter 返回的东西上 注意:所有迭代器必须有一个__iter__实现,它返回迭代器对象本身,而不仅仅是“大多数”。这是a requirement of the iterator protocol:“迭代器需要有一个 __iter__() 方法来返回迭代器对象本身,因此每个迭代器也是可迭代的,并且可以在接受其他可迭代的大多数地方使用。” Python 的其他部分依赖于此;测试某事物是否为迭代器的一种规范且有效的鸭子类型方法是测试obj is iter(someobj) @ShadowRanger 是的,你是绝对正确的。当然,没有什么能阻止你打破这个,但我当然不建议这样做。我会更新以反映这一点。

以上是关于内置函数 iter() 如何将 Python 列表转换为迭代器?的主要内容,如果未能解决你的问题,请参考以下文章

python之迭代器生成器和内置函数,匿名函数

python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)

Python 内置方法

Python内置容器——字典,迭代器,列表解析

Python内置函数(36)——iter

Python中的“迭代”详解