1. 重复
for 循环适合遍历一组已有的数据,或者重复执行一个已知次数的操作。但有些任务无法提前知道要执行多少次:等待用户输入正确内容、不断读取消息直到收到结束标记、重试一个可能暂时失败的操作。
这类任务更适合使用 while 循环。它会在每次执行前检查一个条件,只要条件成立,就继续执行循环体:
1count = 323while count > 0:4print(count)5count -= 167print("开始")
这段代码会打印 3、2、1,然后打印「开始」。它一开始并不知道循环体要执行几次,而是每次根据 count > 0 的结果决定是否继续。
2. while
while 的基本结构是:
1while condition:2print("条件成立时执行")
执行顺序可以分成三步:
- 检查
condition是否为真; - 如果为真,执行缩进的循环体;
- 循环体执行结束后,回到第 1 步重新检查。
只要条件一直为真,循环就会一直执行。因此,循环体通常需要修改条件依赖的变量:
1number = 123while number <= 5:4print(number)5number += 1
number += 1 让 number 最终超过 5,条件变成假,循环才能结束。如果忘记更新 number,程序就会一直打印 1,这种情况叫作无限循环。
while 同样使用缩进表示循环体,冒号不能省略。循环结束之后,程序会继续执行后面的代码:
1number = 323while number > 0:4number -= 156print("循环结束")
3. 条件
while 的条件可以是比较表达式,也可以是布尔变量:
01is_ready = False02checks = 00304while not is_ready and checks < 3:05print("正在检查")06checks += 10708if checks == 3:09is_ready = True1011print("检查完成")
这里用 checks < 3 限制最多检查三次,即使 is_ready 一直没有变成真,循环也能正常结束。为循环设置明确的上限,是避免程序长时间运行的重要习惯。
有时循环会一直等待某个特殊值,这个值通常叫作「结束标记」或「哨兵值」:
1message = ""23while message != "quit":4message = input("请输入内容,输入 quit 结束:")5print(f"收到:{message}")
当用户输入 quit 时,条件 message != "quit" 变成假,循环自然结束。结束标记应该选择不会与正常数据混淆的值,并在文档或提示中明确告诉使用者。
如果条件本身来自函数调用或集合,也要确认它的真值变化符合预期。例如,下面的循环会不断从列表末尾取出任务,直到列表变空:
1tasks = ["读取文件", "整理数据", "保存结果"]23while tasks:4task = tasks.pop()5print(f"正在处理:{task}")
空列表在条件中会被当作假,因此列表为空时循环结束。
4. 控制
break 可以在循环体内部提前结束整个 while 循环。它特别适合处理「满足某个条件后立即停止」的情况:
1number = 123while number <= 10:4if number * number > 30:5break67print(number)8number += 1
当 number * number > 30 时,break 会立即跳出循环,循环后面的 number += 1 也不会执行。
continue 会跳过当前这一次循环,直接回到条件检查的位置:
1number = 023while number < 5:4number += 156if number == 3:7continue89print(number)
这段代码会跳过 3,但仍然打印 1、2、4、5。使用 continue 时,要确保在它之前已经更新了循环条件依赖的变量,否则可能因为一直跳过更新而造成无限循环。
还可以使用 while True 表示「先进入循环,再由内部条件决定什么时候结束」:
1while True:2command = input("请输入命令:")34if command == "quit":5break67print(f"执行命令:{command}")
while True 本身不会自动结束,所以必须保证某条路径能够执行 break。如果循环退出条件很明确,直接写在 while 后面通常更容易阅读。
5. 输入
while 经常用于要求用户重复输入,直到输入满足要求。下面的例子会一直要求输入正数:
1number = int(input("请输入一个正数:"))23while number <= 0:4number = int(input("输入无效,请重新输入:"))56print(f"你输入的正数是:{number}")
这个例子假设用户输入的内容一定能转换成整数。如果用户输入字母,int() 会抛出 ValueError,程序会直接结束。更完整的输入校验需要使用异常处理:
01number = None0203while number is None or number <= 0:04value = input("请输入一个正数:")0506try:07parsed = int(value)08except ValueError:09print("请输入整数")10continue1112if parsed <= 0:13print("数字必须大于 0")14continue1516number = parsed1718print(f"你输入的正数是:{number}")
这里用 number is None 表示还没有得到有效结果,用 continue 处理无效输入。只有把合法数字赋给 number 后,循环条件才会变成假。
6. 实例
下面实现一个最多尝试三次的密码校验。密码正确时立即结束,三次都失败时也会结束:
01correct_password = "python"02attempts = 003is_verified = False0405while attempts < 3:06password = input("请输入密码:")07attempts += 10809if password == correct_password:10is_verified = True11break1213print("密码不正确")1415if is_verified:16print("验证成功")17else:18print("尝试次数已用完")
这个例子同时使用了循环条件和 break:attempts < 3 负责限制最大次数,密码正确时的 break 负责提前结束。把这两个结束原因分别写清楚,比用一个复杂条件更容易维护。
在真实的 FastAPI 或 LangChain 服务中,重试网络请求也可以使用类似思路,但通常还要加入等待时间、异常类型判断和最大重试次数,不能让服务无限重试:
01max_retries = 302attempt = 00304while attempt < max_retries:05attempt += 106print(f"第 {attempt} 次尝试")0708request_succeeded = attempt == 309if request_succeeded:10print("请求成功")11break12else:13print("请求失败,请稍后再试")
这里的 else 与 while 配套,只有循环没有通过 break 提前结束时才会执行。初学阶段可以先掌握 while 和 break,理解循环的结束方式后再使用这种写法。