unique_numbers = set(numbers)在 Python 中任何与迭代器一起工作的东西都可能以某种方式使用迭代器协议 。每当你在 Python 中遍历一个可迭代对象时,你将依赖于迭代器协议 。
生成器是迭代器
所以你可能会想:迭代器看起来很酷,但它们看起来像一个实现细节,我们作为 Python 的使用者,可能不需要关心它们 。
我有消息告诉你:在 Python 中直接使用迭代器是很常见的 。
这里的 squares 对象是一个生成器:
>>> numbers = [1, 2, 3]>>> squares = (n**2 for n in numbers)生成器是迭代器,这意味着你可以在生成器上调用 next 来获得它的下一项:
>>> next(squares)1>>> next(squares)4但是如果你以前用过生成器,你可能也知道可以循环遍历生成器:
>>> squares = (n**2 for n in numbers)>>> for n in squares:... print(n)...149如果你可以在 Python 中循环遍历某些东西,那么它就是可迭代的 。
所以生成器是迭代器,但是生成器也是可迭代的,这又是怎么回事呢?
生成器是可迭代的
我再说一遍:Python 中的每一个迭代器都是可迭代的,意味着你可以循环遍历迭代器 。
因为迭代器也是可迭代的,所以你可以使用内置 next 函数从可迭代对象中获得迭代器:
>>> numbers = [1, 2, 3]>>> iterator1 = iter(numbers)>>> iterator2 = iter(iterator1)请记住,当我们在可迭代对象上调用 iter 时,它会给我们返回一个迭代器 。
当我们在迭代器上调用 iter 时,它会给我们返回它自己:
>>> iterator1 is iterator2True迭代器是可迭代的,所有的迭代器都是它们自己的迭代器 。
def is_iterator(iterable):return iter(iterable) is iterable迷惑了吗?
让我们回顾一些这些措辞 。
一个可迭代对象是你可以迭代的东西 。
一个迭代对象器是一种实际上遍历可迭代对象的代理 。
此外,在 Python 中迭代器也是可迭代的,它们充当它们自己的迭代器 。
所以迭代器是可迭代的,但是它们没有一些可迭代对象拥有的各种特性 。
迭代器没有长度,它们不能被索引:
>>> numbers = [1, 2, 3, 5, 7]>>> iterator = iter(numbers)>>> len(iterator)TypeError: object of type 'list_iterator' has no len()>>> iterator[0]TypeError: 'list_iterator' object is not subscriptable从我们作为 Python 程序员的角度来看,你可以使用迭代器来做的唯一有用的事情是将其传递给内置的 next 函数,或者对其进行循环遍历:
>>> next(iterator)1>>> list(iterator)[2, 3, 5, 7]如果我们第二次循环遍历迭代器,我们将一无所获:
>>> list(iterator)[]你可以把迭代器看作是惰性迭代器,它们是一次性使用,这意味着它们只能循环遍历一次 。
正如你在下面的真值表中所看到的,可迭代对象并不总是迭代器,但是迭代器总是可迭代的:
![python中的for循环在底层是如何开展工作的?](http://img.jiangsulong.com/220404/1T25Q343-1.jpg)
文章插图
全部的迭代器协议
让我们从 Python 的角度来定义迭代器是如何工作的 。
可迭代对象可以被传递给 iter 函数,以便为它们获得迭代器 。
迭代器:
可以传递给 next 函数,它将给出下一项,如果没有下一项,那么它将会引发 StopIteration 异常 。
可以传递给 iter 函数,它会返回一个自身的迭代器 。
这些语句反过来也是正确的:
任何可以在不引发 TypeError 异常的情况下传递给 iter 的东西都是可迭代的
任何可以在不引发 TypeError 异常的情况下传递给 next 的东西都是一个迭代器
当传递给 iter 时,任何返回自身的东西都是一个迭代器
这就是 Python 中的迭代器协议 。
迭代器的惰性
迭代器允许我们一起工作,创建惰性可迭代对象,即在我们要求它们提供下一项之前,它们不做任何事情 。因为可以创建惰性迭代器,所以我们可以创建无限长的迭代器 。我们可以创建对系统资源比较保守的迭代器,可以节省我们的内存,节省 CPU 时间 。
迭代器无处不在
你已经在 Python 中看到过许多迭代器,我也提到过生成器是迭代器 。Python 的许多内置类型也是迭代器 。例如,Python 的 enumerate 和 reversed 对象就是迭代器 。
>>> letters = ['a', 'b', 'c']>>> e = enumerate(letters)>>> e<enumerate object at 0x7f112b0e6510>>>> next(e)(0, 'a')在 Python 3 中,zip, map 和 filter 也是迭代器 。
推荐阅读
- 茶叶市场营销策略中的茶文化营销
- 苏麻喇姑嫁给康熙皇帝了吗 康熙王朝中的苏麻喇姑嫁给康熙了吗
- python多线程爬取youtube视频,外面的世界很精彩
- python爬取拉勾网数据并进行数据可视化
- 淮阴侯列传中的韩信是一个怎样的人
- Python匿名函数的介绍及用途
- Python教程:使用Turtles画出带有花瓣的花
- 9道国宴中的巅峰中国菜 中国国宴菜单
- 对人伸出中指,其中的意思 竖中指是什么意思
- iOS 14中的5个隐藏功能