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