Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。
我们在面试一份工作,面试官要求从代码块中删除所有的for循环。然后他们提到一些关于迭代器的观点同时手指敲打在桌子上并疯狂地大笑。我们很紧张,并且对被分配这个可笑的任务感到沮丧,但是我们将尽最大的努力。
为了理解不用for循环如何循环,我们需要找出for是怎么运作的。
我们要学习在Python中for循环如何工作。在这个过程中,我们需要了解可迭代对象,迭代器和迭代协议。
使用下标循环:一次失败的尝试
我们可能首先尝试通过使用来自于C的传统循环风格来删除for循环:使用下标循环。
这对list有效,但在set上行不通:
这种方法只适用于序列,它是含有索引从0到比序列长度小一的数据类型。列表、字符串和元组是序列。字典、集合和许多其它的可迭代对象不是序列。
我们按照指示实现一个适用于所有可迭代对象而不只是序列的循环结构。
可迭代对象是什么?
在Python的世界,一个可迭代对象是你可以使用一个for循环来进行循环的任何对象。
可迭代对象不总是可索引的,因为它们不总有长度,而且它们不总是有限的。
下面是一个无限的迭代对象,循环时它得到5的倍数:
当我们使用for循环时,我们可以循环遍历这个迭代,像这样:
如果我们从上面的for循环删除break条件,它将永远继续打印。
因此可循环对象可以无限长:这意味着在我们遍历一个可循环对象之前,我们不总是能把它转换成一个列表(或者其它的序列)。我们需要以某种方式让可迭代对象中的每一项分别迭代,同样的方式for循环适用。
可迭代对象和迭代器
好吧,我们已经定义了可迭代对象,但是可迭代对象究竟如何在Python中运作?
可以传递所有的可迭代对象到内置的iter函数来得到一个迭代器。
这是一个有趣的事实,但是什么是迭代器?
迭代器只有一个工作:返回可迭代对象中的“下一个”项。迭代器有点像tally counters,但是它们没有一个复位按钮,而且在可迭代对象中它们给出下一个项,而不是给出下一个数字。
从任何可迭代对象可以得到一个迭代器:
并且可以传递迭代器到next函数来得到它们的下一项:
因此可以传递迭代器到内置的next函数来得到下一项,并且如果没有下一项(因为已经到达结尾)将引发一个StopIteration异常。
迭代器也是可迭代对象
因此在可迭代对象上调用iter得到迭代器。而且在迭代器上调用next得到下一项或者如果没有更多项引发一个StopIteration异常。
实际上不止这些。可以传递迭代器到内置的iter函数来返回它们自身。这意味着迭代器也是可迭代对象。
这一事实导致了一些有趣的后果,而那我们目前没有时间深入。我们将保存这个讨论作为未来的学习探索……
迭代协议
迭代协议是一个很有意思的术语,它的意思是“可迭代对象在Python中究竟如何运作”。
让我们从Python的角度重新定义可迭代对象。
可迭代对象:
1. 可以被传递到iter函数来得到可迭代对象。
2. 没有第2个。需要一个可迭代对象。
迭代器:
1. 可以被传递到next函数,而这得到它们的下一项或者引发StopIteration
2. 当被传递到iter函数,返回它们自身。
这些话反过来也成立。意思是:
1. 传递到iter没有任何错误的任何东西是一个可迭代对象。
2. 传递到next没有任何错误(除了StopIteration)的任何东西是一个迭代器。
3. 传递到iter返回返回自身的任何东西是一个迭代器。
使用迭代器循环
根据我们学到的关于可迭代对象和迭代器的知识,现在应该可以不使用for循环重建一个for循环。这个while循环手动循环某些iterable,打印每个项:
我们可以使用任何可迭代对象调用这个函数,并且它将循环:
上述函数基本上与使用一个for循环的函数相同:
这个for循环自动地做我们手动做的工作:调用iter来得到一个可迭代对象,然后重复调用next直到引发StopIteration异常。
迭代协议用于for循环、元组拆封和所有适用通用可迭代对象的内置函数。使用迭代协议(手动或自动)是唯一的在Python中任何可迭代对象循环的通用方法。
For循环:比它们看起来更复杂
现在我们准备完成面试官分配的非常愚蠢的任务。我们将通过手动使用iter和next循环可迭代对象,从代码中删除所有的for循环。在研究这个任务中,我们学到了什么?
所有你可以循环的是一个可迭代对象。循环可迭代对象通过从一个可迭代对象得到迭代器,然后重复请求迭代器得到下一个项来工作。
迭代器和可迭代对象工作的方式称为迭代协议。列表生成式、元组拆封、for循环和所有其它的迭代协议中迭代依赖的形式。
我会在以后的文章中更多的探讨迭代器。目前知道迭代器是Python中所有迭代的幕后。
英文原文:http://treyhunner.com/2016/12/python-iterator-protocol-how-for-loops-work/
译者:蒲公英
本文深入探讨了Python中for循环的工作原理,介绍了可迭代对象、迭代器及迭代协议的概念,并展示了如何手动实现for循环。
1281

被折叠的 条评论
为什么被折叠?



