循环的 else 子句
Python 的 for 和 while 循环支持一个不太常见但非常有用的 else 子句。它的行为与 if 语句中的 else 截然不同:循环的 else 在循环正常结束时执行,如果循环被 break 提前终止,则 else 不会执行。
基本语义
for-else
在 for 循环中,else 子句在序列迭代完毕、未触发 break 的情况下执行:
for i in range(3):
print(i)
else:
print("循环正常结束")
输出:
0
1
2
循环正常结束
如果加入 break:
for i in range(3):
print(i)
if i == 1:
break
else:
print("这不会执行")
输出 0、1 后,break 终止循环,else 子句被跳过。
while-else
在 while 循环中,else 在循环条件变为假值后执行,同样要求循环未被 break 打断:
count = 3
while count > 0:
print(count)
count -= 1
else:
print("倒计时结束")
输出:
3
2
1
倒计时结束
与 break 的关系
循环 else 的核心设计意图是配合 break 实现搜索逻辑:当循环的目的是查找某个东西时,break 表示"找到了",而 else 表示"找遍了但没找到"。
Python 官方教程用搜索质数的例子完美展示了这一点:
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(f"{n} = {x} * {n//x}")
break
else:
# 循环到底未找到一个因数
print(f"{n} 是质数")
输出:
2 是质数
3 是质数
4 = 2 * 2
5 是质数
6 = 2 * 3
7 是质数
8 = 2 * 4
9 = 3 * 3
注意 else 的缩进层级与内层 for 对齐,而非与 if 对齐。当内层循环遍历所有可能的因数而未触发 break 时,else 执行,确认该数字为质数。
常见误解
循环 else 是 Python 最容易被误解的特性之一,主要源于它与 if-else 的表面相似性。
误解一:else 属于 if
初学者常误以为 else 与前面的 if 配对:
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(f"{n} 是合数")
break
else:
print(f"{n} 是质数") # 错误理解!
如果 else 属于 if,那么每个不满足 n % x == 0 的 x 都会打印一次质数,导致大量重复输出。实际上 else 属于 for,只在整个循环结束后执行一次。
误解二:else 表示"循环失败"
有人觉得 else 应该在循环出错时执行。恰恰相反,else 表示循环成功完成了全部迭代,类似于 try 语句的 else(未发生异常时执行)。官方文档明确指出:"当配合循环使用时,else 子句更像是 try 语句的 else 子句而不像 if 语句的相应子句。"
误解三:else 在循环体执行零次时跳过
for item in []:
print("不会执行")
else:
print("仍然会执行") # 会执行
即使循环体一次都没执行,else 也会执行,因为循环"正常结束"了——它没有被 break 打断。
其他提前结束方式
除了 break,以下方式提前结束循环也会跳过 else:
return(在函数内)- 引发异常(未被捕获)
def search(items, target):
for item in items:
if item == target:
return "找到"
else:
return "未找到"
print(search([1, 2, 3], 2)) # 找到
print(search([1, 2, 3], 5)) # 未找到
return 直接退出函数,循环的 else 不会执行。上面的代码中,else 只在未找到目标时执行,逻辑清晰。
实际应用场景
线性搜索:
def find_index(items, target):
for i, item in enumerate(items):
if item == target:
print(f"在索引 {i} 处找到")
break
else:
print("未找到目标")
find_index(["a", "b", "c"], "b") # 在索引 1 处找到
find_index(["a", "b", "c"], "z") # 未找到目标
验证全部通过:
scores = [85, 92, 78, 88]
for s in scores:
if s < 60:
print("存在不及格成绩")
break
else:
print("所有成绩均合格")
密码尝试限制:
max_attempts = 3
attempts = 0
while attempts < max_attempts:
pwd = input("请输入密码:")
if pwd == "secret":
print("登录成功")
break
attempts += 1
print(f"密码错误,还剩 {max_attempts - attempts} 次机会")
else:
print("尝试次数耗尽,账户已锁定")
是否必须使用 else
循环 else 完全可选。对于不习惯这一特性的开发者,用标志变量也能实现相同逻辑:
found = False
for item in items:
if item == target:
found = True
break
if not found:
print("未找到")
但 else 子句将"搜索"和"未找到"的逻辑绑定在同一语法结构中,减少了临时变量,使意图更加明确。一旦熟悉其语义,循环 else 能让搜索类代码更加紧凑和可读。
理解循环 else 的关键在于记住:它对应的是循环的正常完成,而非条件的否定。把它想象成 try 的 else(未发生异常)而非 if 的 else(条件为假),就能避免绝大多数困惑。