上QQ阅读APP看书,第一时间看更新
第7条 尽量用enumerate取代range
Python内置的range
函数适合用来迭代一系列整数。
如果要迭代的是某种数据结构,例如字符串列表,那么可以直接在这个序列上面迭代,用不着专门通过range
设定一个取值范围,然后把这个范围里的每个整数值,依次当成下标来访问列表中的元素。
当然有的时候,在迭代list
的过程中也需要知道当前处理的这个元素在list
里的位置。例如,我把爱吃的冰激淋口味写在flavor_list
列表里面,在打印每种口味时,我还想指出这种口味在自己心目中的排名。为了实现这样的功能,我们可以用传统的range
方式来实现。
这种写法跟前面那几个例子相比显得有点儿乱。因为我们先得知道列表的长度,然后要根据列表长度构造取值范围,这样才能用其中的每个整数做下标,分别访问列表里的对应元素。这样写步骤太多,读起来比较困难。
Python有个内置的函数,叫作enumerate
,它可以解决刚才的问题。enumerate
能够把任何一种迭代器(iterator)封装成惰性生成器(lazy generator,参见第30条)。这样的话,每次循环的时候,它只需要从iterator里面获取下一个值就行了,同时还会给出本轮循环的序号,即生成器每次产生的一对输出值。下面通过内置的next
函数手动推进enumerate
所返回的这个iterator,给大家演示enumerate
的原理。
enumerate
输出的每一对数据,都可以拆分(unpacking)到for
语句的那两个变量里面(unpacking机制参见第6条),这样会让代码更加清晰。
另外,还可以通过enumerate
的第二个参数指定起始序号,这样就不用在每次打印的时候去调整了。例如,本例可以从1开始计算。
要点
enumerate
函数可以用简洁的代码迭代iterator,而且可以指出当前这轮循环的序号。- 不要先通过
range
指定下标的取值范围,然后用下标去访问序列,而是应该直接用enumerate
函数迭代。 - 可以通过
enumerate
的第二个参数指定起始序号(默认为0)。