- Effective Python:编写高质量Python代码的90个有效方法(原书第2版)
- (美)布雷特·斯拉特金
- 674字
- 2021-08-13 17:10:33
第7条 尽量用enumerate取代range
Python内置的range
函数适合用来迭代一系列整数。
![043-01](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/043-01.jpg?sign=1739068653-iDlGVo5hV5Bsz8ZM5s4gIG7xLYiNdd72-0-8ec121439b97b48cc90204ab064c80b4)
如果要迭代的是某种数据结构,例如字符串列表,那么可以直接在这个序列上面迭代,用不着专门通过range
设定一个取值范围,然后把这个范围里的每个整数值,依次当成下标来访问列表中的元素。
![043-02](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/043-02.jpg?sign=1739068653-dw9yHNIbE7wXdmL7GN0U28Lo4c2BFmdl-0-6a32f16a9118796813aa7dfab2e15736)
当然有的时候,在迭代list
的过程中也需要知道当前处理的这个元素在list
里的位置。例如,我把爱吃的冰激淋口味写在flavor_list
列表里面,在打印每种口味时,我还想指出这种口味在自己心目中的排名。为了实现这样的功能,我们可以用传统的range
方式来实现。
![043-03](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/043-03.jpg?sign=1739068653-fZdPDFbzFAnJpFFAgPT7WCPPfVmtPzHJ-0-d57dd7e2f1300e1c5b6986b66ae8ca4d)
这种写法跟前面那几个例子相比显得有点儿乱。因为我们先得知道列表的长度,然后要根据列表长度构造取值范围,这样才能用其中的每个整数做下标,分别访问列表里的对应元素。这样写步骤太多,读起来比较困难。
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=1739068653-UiMP8YahGIFTNOM1CsKcn7pW7QVI8dqF-0-24f36ccf6c5dd7245e005e74428ff22d)
enumerate
输出的每一对数据,都可以拆分(unpacking)到for
语句的那两个变量里面(unpacking机制参见第6条),这样会让代码更加清晰。
![044-02](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/044-02.jpg?sign=1739068653-i93z1aFneZWzUdvu7UBRqb3Y3o9weshw-0-b55d3d0d2a16d79cafaad74521891f2d)
另外,还可以通过enumerate
的第二个参数指定起始序号,这样就不用在每次打印的时候去调整了。例如,本例可以从1开始计算。
![044-03](https://epubservercos.yuewen.com/873E3D/20818200901954706/epubprivate/OEBPS/Images/044-03.jpg?sign=1739068653-reelsvpjhOPiGnbTpOCVqPEq3genKr7l-0-536770349b5be2e32207581e291cedea)
要点
enumerate
函数可以用简洁的代码迭代iterator,而且可以指出当前这轮循环的序号。- 不要先通过
range
指定下标的取值范围,然后用下标去访问序列,而是应该直接用enumerate
函数迭代。 - 可以通过
enumerate
的第二个参数指定起始序号(默认为0)。