4. 序列遍历技巧:for循环遍历、enumerate()获取索引、zip()并行遍历
遍历序列,说白了就是挨个儿访问里面的元素。这事儿看起来简单,但写得好不好,直接关系到代码的优雅程度和坑的数量。我见过不少新手,甚至有些老手,在遍历上栽过跟头。
今天咱们就把这三种核心遍历方式掰开揉碎,讲清楚。
4.1 for循环遍历:最基础的玩法
for 循环是 Python 里遍历序列的标配。你想想看,一个列表、元组、字符串,甚至字典,都能用 for 直接撸一遍。
fruits = ['苹果', '香蕉', '橘子', '葡萄']
for fruit in fruits:
print(fruit)
输出很简单:
苹果
香蕉
橘子
葡萄
我个人习惯,只要不需要索引,优先用这种直接遍历。代码干净,读起来也舒服。
for char in text 是最直接的方式。
4.2 enumerate()获取索引:既要元素又要位置
很多时候,我们不光要元素,还得知道它在序列里的位置。比如你要修改列表里的某些项,或者记录每个元素的下标。
新手常犯的错误是这么写:
fruits = ['苹果', '香蕉', '橘子', '葡萄']
for i in range(len(fruits)):
print(i, fruits[i])
嗯,这代码能跑,但不够 Pythonic。每次都要 range(len(...)),看着就啰嗦。
更好的做法是用 enumerate():
for i, fruit in enumerate(fruits):
print(i, fruit)
输出:
0 苹果
1 香蕉
2 橘子
3 葡萄
我曾经在一个数据处理项目里,需要同时记录每行数据的行号和内容。一开始用的 range(len()),后来改成 enumerate(),代码量直接减半,可读性也上去了。
enumerate() 默认从 0 开始计数。如果你希望从 1 开始,可以传第二个参数:enumerate(fruits, start=1)。
4.3 zip()并行遍历:同时处理多个序列
有时候,你需要同时遍历两个或多个序列。比如你有两个列表,一个存名字,一个存分数,你想把它们一一对应地打印出来。
没有 zip() 的时候,你可能得这么写:
names = ['张三', '李四', '王五']
scores = [85, 92, 78]
for i in range(len(names)):
print(names[i], scores[i])
这代码有个隐患——如果两个列表长度不一样,就会报索引越界的错。我踩过这个坑,当时排查了半天才发现是数据源出了问题。
用 zip() 就安全多了:
for name, score in zip(names, scores):
print(name, score)
输出:
张三 85
李四 92
王五 78
zip() 会以最短的序列为准,自动截断。这既是优点也是坑——如果你没意识到数据长度不一致,可能会悄无声息地丢掉数据。
zip(),结果因为其中一个文件少了一行,导致最后一条数据被静默丢弃。后来我养成了一个习惯:在 zip() 之前,先检查两个序列的长度是否一致。
4.4 三种遍历方式的对比
| 方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
for item in seq |
只需要元素,不需要索引 | 代码最简洁,可读性最高 | 无法获取元素位置 |
enumerate(seq) |
需要元素和索引 | 比 range(len()) 更优雅 |
稍微多一层解包 |
zip(seq1, seq2) |
同时遍历多个序列 | 自动对齐,代码简洁 | 以最短序列为准,可能丢数据 |
4.5 组合使用:enumerate() + zip()
这两个函数还能组合使用。比如你有三个列表,既要并行遍历,又要记录索引:
names = ['张三', '李四', '王五']
scores = [85, 92, 78]
grades = ['B', 'A', 'C']
for i, (name, score, grade) in enumerate(zip(names, scores, grades)):
print(f'{i}: {name} - {score}分 - {grade}等级')
输出:
0: 张三 - 85分 - B等级
1: 李四 - 92分 - A等级
2: 王五 - 78分 - C等级
这里要注意括号的嵌套顺序。我刚开始用的时候也经常搞混,多写几次就习惯了。
enumerate() 和 zip() 的组合几乎是标配。掌握它们,能让你的代码从「能跑」变成「漂亮」。
4.6 知识结构图
下面这张图帮你理清这三种遍历方式的关系和适用场景:
4.7 实战避坑总结
- 别滥用
range(len())——能用enumerate()就别手写索引循环。 zip()会静默截断——如果两个序列长度不一致,短的说了算。提前检查长度是个好习惯。- 嵌套解包注意括号——
enumerate(zip(...))的括号顺序别搞反了。 - 遍历字典时——默认遍历的是键。如果需要键值对,用
.items()。
这三种遍历技巧,说白了就是 Python 给咱们准备的「三板斧」。用好了,代码既简洁又高效。我建议你平时写代码时,有意识地用 enumerate() 和 zip() 替代那些老套的写法,慢慢就形成肌肉记忆了。