高效Python90条之第7条 尽量用enumerate取代range ¶
要点:
- enumerate函数可以用简洁的代码迭代iterator,而且可以指出当前这轮循环的序号。
- 不要先通过range指定下标的取值范围,然后用下标去访问序列,而是应该直接用enumerate函数迭代。
- 可以通过enumerate的第二个参数指定起始序号(默认为0)。
Python内置的range
函数适合用来迭代一系列整数。
from random import randint
random_bits = 0
for i in range(32):
if randint(0, 1):
random_bits |= 1 << i # 运算符|是二进制OR操作
print(bin(random_bits))
# 0b1101110010100110001001111011011
如果要迭代的是某种数据结构,例如字符串列表,那么可以直接在这个序列上面迭代,不需要通过range
。
flavor_list = ["vanilla", "chocolate", "pecan", "strawberry"]
for flavor in flavor_list:
print(f"{flavor} is delicious")
# vanilla is delicious
# chocolate is delicious
# pecan is delicious
# strawberry is delicious要点:
* enumerate函数可以用简洁的代码迭代iterator,而且可以指出当前这轮循环的序号。
* 不要先通过range指定下标的取值范围,然后用下标去访问序列,而是应该直接用enumerate函数迭代。
* 可以通过enumerate的第二个参数指定起始序号(默认为0)。
通过传统的range
方法,给每种口味添加序列号。但步骤有些太多,先得知道列表的长度,然后要根据列表长度构造取值范围,用其中的每个整数做下标,分别访问列表里的对应元素。
flavor_list = ["vanilla", "chocolate", "pecan", "strawberry"]
for i in range(len(flavor_list)):
flavor = flavor_list[i]
print(f"{i + 1}: {flavor}")
# 1: vanilla
# 2: chocolate
# 3: pecan
# 4: strawberry
Python的内置的函数enumerate
,能够把任何一种迭代器(iterator)封装成惰性生成器(lazy generator,参见Rule30)。 这样每次循环的时候,它只需要从iterator里面获取下一个值就行了,同时还会给出本轮循环的序号,即生成器每次产生的一对输出值。
下面通过内置的next
函数手动推进enumerate
所返回的这个iterator,来演示enumerate
。
flavor_list = ["vanilla", "chocolate", "pecan", "strawberry"]
it = enumerate(flavor_list)
print(next(it)) # (0, 'vanilla')
print(next(it)) # (1, 'chocolate')
print(next(it)) # (2, 'pecan')
print(next(it)) # (3, 'strawberry')
print(next(it)) # Error: StopIteration
enumerate
输出的每一对数据,都可以拆分(unpacking)到for
语句的那两个变量里面,这样会让代码更加清晰。
flavor_list = ["vanilla", "chocolate", "pecan", "strawberry"]
for i, flavor in enumerate(flavor_list):
print(f"{i + 1}: {flavor}")
# 1: vanilla
# 2: chocolate
# 3: pecan
# 4: strawberry
for i, flavor in enumerate(flavor_list, 1):
print(f"{i}: {flavor}")
# 1: vanilla
# 2: chocolate
# 3: pecan
# 4: strawberry
enumerate
也可以用在处理二维数组上。
data = [
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30],
[40, 40, 40],
[50, 50, 50],
]
for i, row in enumerate(data):
if i + 5 < len(data):
# 对第 i 行和第 i+5 行进行加法运算
result = [a + b * 10 for a, b in zip(row, data[i + 5])]
print(f"Row {i} + Row {i+5} * 5 = {result}")