![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=1738861902-UhTm6O1yEfTesrusnz1Y5eTB3bAzZlAC-0-06ac6296c050cd73e8d72c4359836c6a)
如果要迭代的是某种数据结构,例如字符串列表,那么可以直接在这个序列上面迭代,用不着专门通过range
设定一个取值范围,然后把这个范围里的每个整数值,依次当成下标来访问列表中的元素。
![043-02](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/043-02.jpg?sign=1738861902-hIuR9RDfqTugYOuOwM5WRCKEJCgLM4N5-0-4dfd93a547e6acf1730629a5033bd617)
当然有的时候,在迭代list
的过程中也需要知道当前处理的这个元素在list
里的位置。例如,我把爱吃的冰激淋口味写在flavor_list
列表里面,在打印每种口味时,我还想指出这种口味在自己心目中的排名。为了实现这样的功能,我们可以用传统的range
方式来实现。
![043-03](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/043-03.jpg?sign=1738861902-Zr782c7T6cvtyML5UipjgmL3ZPUnv0V5-0-82d8b72c2a586ffd20392a17c756434a)
这种写法跟前面那几个例子相比显得有点儿乱。因为我们先得知道列表的长度,然后要根据列表长度构造取值范围,这样才能用其中的每个整数做下标,分别访问列表里的对应元素。这样写步骤太多,读起来比较困难。
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=1738861902-orrHXjzz8fXHcRvvef2W0YHftwrPUrNq-0-916778df99db4bc3e69ca121f1d549e3)
enumerate
输出的每一对数据,都可以拆分(unpacking)到for
语句的那两个变量里面(unpacking机制参见第6条),这样会让代码更加清晰。
![044-02](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/044-02.jpg?sign=1738861902-UAsBADdlniHzznSFJ719cf0A5khlESJp-0-f1d94e1a351438d2b7a96997aa5d9a41)
另外,还可以通过enumerate
的第二个参数指定起始序号,这样就不用在每次打印的时候去调整了。例如,本例可以从1开始计算。
![044-03](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/044-03.jpg?sign=1738861902-XiZJj2GFnze9B5wUZdGJUUMXEP8cCx0b-0-7c01ac0453bae982598a58e40841e72f)
要点
enumerate
函数可以用简洁的代码迭代iterator,而且可以指出当前这轮循环的序号。- 不要先通过
range
指定下标的取值范围,然后用下标去访问序列,而是应该直接用enumerate
函数迭代。 - 可以通过
enumerate
的第二个参数指定起始序号(默认为0)。