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