讲解
Python 的 for 循环语义是「遍历」:for 变量 in 可迭代对象: 依次把容器里的每个元素交给循环体。遍历列表 for fruit in fruits、遍历字符串 for ch in 'abc'、遍历字典的键 for key in d——没有别家语言那种「初始化;条件;自增」的三段式 for,需要固定次数时用 range() 生成整数序列。这种设计让大多数循环一行就能写清楚,也消灭了「下标越界」这一整类 bug。
range(start, stop, step) 生成从 start 到 stop(不含)、步长为 step 的整数序列:range(5) 是 0 到 4,range(1, 11) 是 1 到 10,range(10, 0, -1) 是 10 倒数到 1。它是个「惰性」序列,不占内存,len(range(10**9)) 也没问题。遍历时同时需要下标和元素,用内置的 enumerate(items) 得到 (下标, 元素) 对,可选第二参数指定起始下标;并行遍历多个列表用 zip(a, b) 配对,以最短的那个为准。
for 同样有 else 子句:循环没被 break 打断、完整跑完时执行,语义和 while...else 一样服务于「找东西」。循环里要修改被遍历的列表是大忌——边遍历边删元素会跳过数据,正确做法是用列表推导式或切片遍历副本(for item in items[:]:)。最后记住 reversed() 反向遍历和 sorted() 排序遍历这两个内置帮手,它们都返回新序列,不动原数据。
示例
# 遍历列表:for 的本职工作
fruits = ['苹果', '香蕉', '橙子']
for fruit in fruits:
print('水果:', fruit)
# range:固定次数
total = 0
for i in range(1, 101): # 1 到 100
total += i
print('1 到 100 的和:', total)
print('倒数:', list(range(5, 0, -1)))
# enumerate:下标和元素一起要
for index, fruit in enumerate(fruits, start=1):
print(f'第 {index} 个:{fruit}')
# zip:并行遍历
names = ['小明', '小红']
scores = [90, 85, 70] # 注意 scores 更长
for name, score in zip(names, scores):
print(f'{name}: {score}') # 70 被忽略——zip 以最短的为准
# for...else:找素数之外的例子——找第一个偶数
nums = [1, 3, 7, 8, 9]
for n in nums:
if n % 2 == 0:
print('第一个偶数:', n)
break
else:
print('没有偶数')
# sorted 与 reversed 不动原列表
print('排序遍历:', sorted([3, 1, 2]))
print('反向遍历:', list(reversed(fruits)))
常见坑
- range 不含右端点:range(1, 10) 到 9 为止。想要 1 到 10 就写 range(1, 11),「含头不含尾」和切片一致。
- 边遍历边删元素:for x in items: items.remove(x) 会因为列表在迭代中收缩而跳过元素。改用 [x for x in items if 保留条件]。
- enumerate 的下标默认从 0 开始:展示给用户看时记得 start=1,或者下标加一。
- 对 zip 结果二次遍历:zip 返回的是一次性迭代器,遍历完就空了。需要反复用就 list(zip(a, b)) 存起来。
小结
for 遍历一切可迭代对象,range 生成次数,enumerate 带下标,zip 并行配对;for...else 处理「没找到」。下一节进入最常用的数据结构:列表。