共计 1624 个字符,预计需要花费 5 分钟才能阅读完成。
在 Python 中,很多时候我们需要遍历一个序列的同时获取每个元素的索引。很多初学者会这样做:
fruits = ['apple', 'banana', 'cherry']
for i in range(len(fruits)):
print(i, fruits[i])
虽然这段代码可以正常运行,但是并不是 Pythonic 的写法,代码显得冗长而不直观。更推荐的写法是使用 enumerate() 函数。
一、什么是 enumerate?
enumerate()是 Python 内置函数,它将一个可迭代对象(如列表、元组或字符串)组合为一个索引序列,同时返回索引和对应的值。它的语法如下:
enumerate(iterable, start=0)
iterable:任何可迭代对象;start:索引起始值,默认为 0。
来看一个简单示例:
fruits = ['apple', 'banana', 'cherry']
for index, fruit in enumerate(fruits):
print(index, fruit)
输出为:
0 apple
1 banana
2 cherry
这样写的好处在于:
- 不需要手动使用
range()和len(); - 可读性更高;
- 代码更简洁优雅。
二、设置自定义起始索引
如果你不想从 0 开始索引,比如你想从 1 开始,也非常简单,只需要设置 start 参数:
for index, fruit in enumerate(fruits, start=1):
print(index, fruit)
输出为:
1 apple
2 banana
3 cherry
这在处理用户列表、菜单、表格等具有自然编号场景中非常实用。
三、与字典组合使用
假设你有一个学生列表,需要自动生成编号,可以这样使用enumerate:
students = ['Tom', 'Lucy', 'Jack']
student_dict = {i: name for i, name in enumerate(students, start=1)}
print(student_dict)
输出:
{1: 'Tom', 2: 'Lucy', 3: 'Jack'}
四、和 zip 的对比
有人可能会问,zip(range(len(fruits)), fruits)和 enumerate(fruits) 有什么区别?来看示例:
for i, fruit in zip(range(len(fruits)), fruits):
print(i, fruit)
虽然也能达到相同目的,但 enumerate() 更语义清晰、性能更优。zip()会先将两个对象组合为新的可迭代对象,而 enumerate() 是专门为这种“需要索引”的场景设计的。
五、避免使用反模式
反模式如下:
i = 0
for fruit in fruits:
print(i, fruit)
i += 1
虽然这段代码看起来没什么问题,但它:
- 多了一个外部变量
i; - 需要手动维护
i的增量; - 容易引起出错或混乱。
这种写法不符合 Python 的设计哲学“优雅”、“简洁”、“明确”。
六、enumerate 处理嵌套循环
enumerate()也可以配合嵌套列表处理二维结构。比如:
matrix = [[1, 2],
[3, 4],
[5, 6]
]
for row_index, row in enumerate(matrix):
for col_index, value in enumerate(row):
print(f'[{row_index}, {col_index}] = {value}')
输出为:
[0, 0] = 1
[0, 1] = 2
[1, 0] = 3
[1, 1] = 4
[2, 0] = 5
[2, 1] = 6
这在处理表格、图像、地图等二维数据时非常有用。
七、小结
enumerate()是获取元素索引和内容的首选方法;- 它比
range(len(...))更清晰、更安全; - 支持自定义起始索引;
- 可用于字典生成、嵌套结构等复杂场景。
建议从今天起,逐步将涉及索引遍历的代码改写为 enumerate() 风格,你会发现代码更易读、也更优雅。
掌握 enumerate() 是迈向 Python 高级用法的重要一步。