Python enumerate 用于索引和值对
Python enumerate 会给可迭代对象添加一个递增索引,在遍历时返回 (索引, 值) 对。
当你需要每个元素的位置(例如编号输出或标签)时使用它。
这是将元素与其位置配对的内置模式,适用于列表、生成器或文件行。
Python Enumerate 示例:编号输出
输出:
输出将显示在这里...
输出:
1. 发货
2. 给客户发邮件
示例解析
enumerate(tasks, start=1)将每个任务与其位置配对。start=1让编号更符合人类阅读习惯。- 输出展示了每个任务的编号。
Python enumerate 常见坑
错误 1:忘记编号从 0 开始。
for line_no, row in enumerate(rows):
print(f"第 {line_no} 行: {row['sku']}")
for line_no, row in enumerate(rows, start=1):
print(f"第 {line_no} 行: {row['sku']}")
原因:enumerate 默认从 0 开始,这对索引是正确的,但对面向用户的行号会造成混淆。
错误 2:枚举字典却以为得到的是值。
region_totals = {"西部": 1200, "东部": 980}
for i, total in enumerate(region_totals):
print(i, total)
region_totals = {"西部": 1200, "东部": 980}
for i, (region, total) in enumerate(region_totals.items(), start=1):
print(i, region, total)
原因:遍历 dict 得到的是键,因此 enumerate 会将索引与键配对,除非你遍历 .items()。
如果你需要键/值查找模式,请看 Python dict 示例。
错误 3:为大数据构建 list(enumerate(...))。
indexed_rows = list(enumerate(rows, start=1))
for line_no, row in indexed_rows:
print(line_no, row)
for line_no, row in enumerate(rows, start=1):
print(line_no, row)
原因:list() 会把所有对加载进内存,而 enumerate 本身是惰性的,可以流式处理。
enumerate vs range(len()):怎么选
使用 enumerate 当… | 使用 range(len()) 当… |
|---|---|
| 你需要索引和元素一起使用。 | 你只需要数字索引。 |
| 你遍历任意可迭代对象,包括生成器。 | 你需要按自定义步长跳跃或只按索引遍历。 |
| 你希望循环更清晰、无需手动索引。 | 你需要索引用于切片或随机访问。 |
经验法则:需要索引+值时用 enumerate;索引本身是重点时用 range(len())。
如果你只需要索引运算,请看更深入的 Python range 示例。
性能考虑
enumerate 是 O(n) 且惰性的,因此除非用 list() 包裹,否则不会额外分配成对列表。实际使用中,它比在循环内调用 list.index() 更快更清晰(后者可能让循环变成 O(n^2))。如果你只是给行加编号,enumerate 能保持常量内存同时提供行号。
Enumerate 的其他用法
扫描日志时标记错误行。
lines = [
"INFO 已连接",
"错误 超时",
"INFO 重试",
]
for line_no, line in enumerate(lines, start=1):
if "错误" in line:
print(f"第 {line_no} 行: {line}")
这样可以保留精确行号,便于调试和事故复盘。
它同样适用于文件,因为 enumerate 接受任何可迭代对象。
按索引原地规范化列表。
names = [" ada", "grace ", " linus"]
for i, name in enumerate(names):
# 需要原地修改列表时按索引更新
names[i] = name.strip().title()
print(names)
这样数据仍在同一个列表中,同时你拥有用于回写的索引。 比手动计数更清晰,也让循环保持可读性。