专项练习 · 8 分钟阅读

Python enumerate 与 zip 练习:更干净的循环

循环里的大多数错误都来自记账:索引悄悄偏移、计数器从错误的位置开始,或者两个列表已经对不上却没人发现。enumerate 和 zip 把这些关系写进循环头部,让问题更容易看见。

让 enumerate 负责索引

循环变量会收到一对值,直接解包成索引和元素即可。不需要初始化计数器,也不会忘记加一。原列表保持不变。

colors = ["red", "green", "blue"]
for index, color in enumerate(colors):
    print(index, color)

一次拿到索引和值

选择适合人的起始编号

计算机通常从零开始数,但人往往期待从一开始。start 参数只改变编号,不会切片,也不会跳过第一个元素。

for number, color in enumerate(["red", "green"], start=1):
    print(f"{number}: {color}")

从一编号

用 zip 并行遍历列表

zip 先配第一项,再配第二项,依此类推,并在最短的输入处停止。调试时可以打印 list(zip(...)),直接看到配对,而不是一个迭代器对象。

names = ["Ada", "Grace"]
scores = [92, 88]
for name, score in zip(names, scores):
    print(f"{name}: {score}")

两个列表,一个循环

长度必须一致时使用严格 zip

悄悄截断对某些数据很方便,对另一些数据却很危险。Python 3.10 增加了 strict=True,输入长度不同时会抛出 ValueError。缺失一行应该被看见时,就用它。

pairs = list(zip([1, 2], ["a", "b"], strict=True))
print(pairs)

数据不匹配时明确失败

用两个列表构建字典

dict 接收由键值对组成的可迭代对象,而 zip 产生的正是这种形状。如果源数据可能重复,先检查重复键;同一个键出现两次时,dict 会保留后面的值。

names = ["Ada", "Grace"]
scores = [92, 88]
print(dict(zip(names, scores)))

配对变成映射

你的练习清单

常见问题

enumerate 会复制列表吗?

不会。它返回一个迭代器,读取已有的可迭代对象并产生索引-元素对。

zip 为什么会提前停止?

只要有任意一个输入用完,zip 就结束。这让它可以配合无限迭代器,但也可能掩盖缺失数据。

可以同时 zip 三个列表吗?

可以。zip 接受任意数量的可迭代对象,并产生包含每个输入一个值的元组。

练习 enumerate 与 zip

12 道题,覆盖索引、并行列表、严格 zip 和字典构建。

打开练习

继续阅读: