内置函数 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 列表转换为迭代器?的主要内容,如果未能解决你的问题,请参考以下文章