enumerate 是 Python 内置的一个非常实用的函数,用于在迭代过程中同时获取元素的索引和值,使代码更简洁、更 Pythonic
1. 基本语法
python
enumerate(iterable, start=0)
-
iterable:任何可迭代对象(如列表、元组、字符串、range 等) -
start(可选):索引的起始值,默认为 0
enumerate 返回一个枚举对象 (iterator),每次迭代生成一个包含 (索引, 元素) 的元组。
2. 基本用法示例
2.1 遍历列表并获取索引与值
python
fruits = ['apple', 'banana', 'cherry']
for index, fruit in enumerate(fruits):
print(index, fruit)
输出:
0 apple
1 banana
2 cherry
2.2 指定起始索引
for index, fruit in enumerate(fruits, start=1):
print(index, fruit)
输出:
1 apple
2 banana
3 cherry
2.3 遍历字符串
python
for i, ch in enumerate("hello"):
print(i, ch)
输出:
0 h
1 e
2 l
3 l
4 o
3. enumerate 的返回值
enumerate 返回的是一个迭代器(iterator),它并不会一次性生成所有元素,而是在每次迭代时惰性生成一个元组。如果需要查看所有结果,可以将其转换为列表:
python
seasons = ['Spring', 'Summer', 'Autumn', 'Winter']
list(enumerate(seasons))
输出: [(0, 'Spring'), (1, 'Summer'), (2, 'Autumn'), (3, 'Winter')]
python
list(enumerate(seasons, start=1))
输出: [(1, 'Spring'), (2, 'Summer'), (3, 'Autumn'), (4, 'Winter')]
4. 常见应用场景
4.1 在循环中修改列表元素
python
nums = [10, 20, 30]
for i, val in enumerate(nums):
nums[i] = val * 2 # 修改原列表
print(nums) # [20, 40, 60]
4.2 同时遍历两个序列(与 zip 结合)
python
names = ['Alice', 'Bob', 'Charlie']
scores = [85, 92, 78]
for i, (name, score) in enumerate(zip(names, scores)):
print(f"第{i+1}名: {name} - {score}分")
4.3 查找元素首次出现的索引
python
def find_first(seq, target):
for i, val in enumerate(seq):
if val == target:
return i
return -1
4.4 在推导式中使用
生成 (索引, 值) 的列表
python
pairs = [(i, v) for i, v in enumerate('abc')]
print(pairs) # [(0, 'a'), (1, 'b'), (2, 'c')]
只保留索引为偶数的元素
python
even_indexed = [v for i, v in enumerate('hello') if i % 2 == 0]
print(even_indexed) # ['h', 'l', 'o']
5. 与 range(len(seq)) 的比较
传统做法:
python
for i in range(len(fruits)):
print(i, fruits[i])
这种方式需要两次索引访问,略显冗长。
而 enumerate 直接提供索引和值,代码更清晰、更符合 Python 风格("Pythonic")。
注意 :如果只需要值而不需要索引,直接 for item in seq 即可,无需用 enumerate。
6. 高级用法
6.1 将枚举对象转为字典
python
colors = ['red', 'green', 'blue']
color_dict = dict(enumerate(colors))
print(color_dict) # {0: 'red', 1: 'green', 2: 'blue'}
6.2 在类中实现 __iter__ 返回 enumerate
python
class MyList:
def __init__(self, items):
self.items = items
def __iter__(self):
return enumerate(self.items)
6.3 使用 itertools.count 替代 start 参数(复杂场景)
对于更复杂的计数需求,enumerate 的 start 参数通常足够。如果希望索引步长不为1,可结合 itertools.count:
python
from itertools import count
for i, val in zip(count(step=2), 'abc'):
print(i, val)
输出: 0 a / 2 b / 4 c
7. 注意事项
-
enumerate是惰性求值的,不会立即生成所有对,仅在迭代时逐个产生,因此内存友好。 -
传入的
iterable可以是任何可迭代对象,包括文件对象、生成器等。 -
enumerate返回的元组是不可变的,但不影响对其内部元素的操作。