上一章讲完条件判断以后,程序已经可以根据条件选择不同的执行路线。不过,有些代码并不是只执行一次。例如,输出 1 到 10、逐个处理字符串中的字符,或者在用户输入错误时重新询问,这些情况都需要使用循环。
思维导图

Python 中常用的循环有 while 和 for。while 根据条件决定是否继续执行,for 用来依次取出一组数据中的每个元素。本章还会讲到 range()、嵌套循环、break、continue 和循环中的 else。

一、循环是怎样执行的
没有循环时,重复输出三次需要写三条语句:
python
print("开始学习 Python")
print("开始学习 Python")
print("开始学习 Python")
使用循环以后,可以把重复的次数交给程序控制:
python
for _ in range(3):
print("开始学习 Python")
运行结果没有变化,但是重复次数不再写死在三条相同的语句中。后面需要执行十次时,只需要把 range(3) 改成 range(10)。
循环通常包含两个部分:
- 循环条件或者需要遍历的数据;
- 每次循环都要执行的代码块。
循环体仍然通过缩进表示。缩进结束以后,后面的语句就不属于循环了:
python
for number in range(3):
print(number)
print("循环结束")
输出结果为:
txt
0
1
2
循环结束
二、while 循环
while 会先判断条件。条件为 True 时执行循环体,执行完以后再次判断;条件变成 False,循环才会结束。
基本语法如下:
python
while 条件:
循环体
例如,输出 1 到 5:
python
number = 1
while number <= 5:
print(number)
number += 1
运行结果为:
txt
1
2
3
4
5
这段代码的执行过程是:
- 先把
number设置为1; - 判断
number <= 5; - 条件成立,输出当前的
number; - 执行
number += 1; - 回到
while,重新判断条件。
当 number 增加到 6 时,条件不再成立,循环结束。

1. 使用 while 累加
循环不只可以重复输出,也可以不断修改同一个结果。例如,计算 1 到 100 的和:
python
number = 1
total = 0
while number <= 100:
total += number
number += 1
print(total)
输出结果为:
txt
5050
这里的 number 用来记录当前处理到哪个数字,total 用来保存已经累加的结果。两个变量的作用不同,不要混在一起。
2. 根据用户输入结束循环
如果事先不知道循环要执行多少次,可以把用户输入作为结束条件:
python
command = ""
while command != "quit":
command = input("请输入命令,输入 quit 退出:")
print("收到命令:", command)
只要输入的内容不是 quit,程序就会继续询问。输入 quit 后,当前这一次循环仍然会执行后面的 print(),然后在下一次判断时结束。
如果不希望输出 quit,可以把处理逻辑放到条件判断中:
python
command = ""
while command != "quit":
command = input("请输入命令,输入 quit 退出:")
if command != "quit":
print("收到命令:", command)
三、无限循环
while 的条件如果一直为 True,循环就不会自行结束:
python
number = 1
while number <= 5:
print(number)
上面的代码没有修改 number,所以 number <= 5 会一直成立。程序会不断输出 1。
有些程序会主动使用无限循环,再在循环内部决定何时退出:
python
while True:
command = input("请输入命令:")
if command == "quit":
break
print("正在执行:", command)
这种写法本身没有问题,不过循环内部必须存在能够执行到的退出条件。程序意外进入无限循环时,可以在终端中按 Ctrl + C 停止运行。
四、for 循环
for 用来依次取出可迭代对象中的元素。字符串、列表、元组、字典、集合和 range() 生成的整数序列都可以被遍历。
基本语法如下:
python
for 变量 in 可迭代对象:
循环体
例如,逐个读取字符串中的字符:
python
language = "Python"
for char in language:
print(char)
输出结果为:
txt
P
y
t
h
o
n
每次循环时,char 会保存当前取出的字符。循环结束以后,字符串中的六个字符都已经处理过一次。

1. 遍历列表
列表会在后面的章节中详细讲,这里先看它在循环中的基本用法:
python
names = ["张三", "李四", "王五"]
for name in names:
print("当前用户:", name)
输出结果为:
txt
当前用户: 张三
当前用户: 李四
当前用户: 王五
2. 循环变量的命名
循环变量应该能说明当前取出的内容:
python
for student in students:
print(student)
for file_name in file_names:
print(file_name)
只在很短的计数循环中,才会经常使用 i、j 这样的名称。循环变量完全不会被使用时,可以写成下划线 _:
python
for _ in range(3):
print("重新尝试")
下划线并没有特殊的语法限制,它只是告诉读代码的人:这个变量不会在循环体中使用。
五、range() 生成整数序列
range() 经常和 for 一起使用。它可以接收一个、两个或者三个参数。
1. range(stop)
只传一个参数时,序列从 0 开始,到 stop 之前结束:
python
for number in range(5):
print(number)
输出结果为:
txt
0
1
2
3
4
5 不会包含在结果中。
2. range(start, stop)
传入两个参数时,第一个参数是起点,第二个参数是终点:
python
for number in range(1, 6):
print(number)
输出 1 到 5。仍然需要注意,终点 6 不包含在结果中。
3. range(start, stop, step)
第三个参数表示步长:
python
for number in range(0, 11, 2):
print(number)
输出结果为:
txt
0
2
4
6
8
10
步长也可以是负数:
python
for number in range(5, 0, -1):
print(number)
输出结果为:
txt
5
4
3
2
1
使用负步长时,起点必须大于终点。下面的代码不会输出任何内容:
python
for number in range(1, 5, -1):
print(number)
因为序列需要向下递减,但是起点 1 已经小于终点 5。

4. range 对象
range() 返回的是一个 range 对象,并不是已经创建好的列表:
python
numbers = range(1, 6)
print(numbers)
print(type(numbers))
输出结果为:
txt
range(1, 6)
<class 'range'>
需要查看其中的全部值时,可以临时转换成列表:
python
print(list(range(1, 6)))
输出结果为:
txt
[1, 2, 3, 4, 5]
六、同时取得索引和值
遍历一组数据时,有时还需要知道当前元素的位置。可以使用 enumerate():
python
languages = ["Python", "Java", "Go"]
for index, language in enumerate(languages):
print(index, language)
输出结果为:
0 Python
1 Java
2 Go
enumerate() 默认从 0 开始计数,也可以通过 start 指定起点:
python
for number, language in enumerate(languages, start=1):
print(number, language)
输出结果为:
1 Python
2 Java
3 Go
如果只是为了得到索引,不建议写成下面这样:
python
for index in range(len(languages)):
print(index, languages[index])
这段代码可以运行,但是 enumerate() 更直接,也不需要手动根据索引再次取值。
七、break 提前结束循环
break 会立即结束它所在的那一层循环。下面的程序在找到目标数字以后停止查找:
python
numbers = [3, 8, 12, 19, 24]
target = 12
for number in numbers:
if number == target:
print("已经找到:", target)
break
print("检查:", number)
输出结果为:
检查: 3
检查: 8
已经找到: 12
执行 break 以后,后面的 19 和 24 不会再被检查。
break 只能写在循环内部。如果循环中还有条件判断,它结束的仍然是循环,不只是 if 代码块。
八、continue 跳过本次循环
continue 不会结束整个循环,它只会跳过本次剩余的代码,直接进入下一次循环。
例如,只输出 1 到 10 中的奇数:
python
for number in range(1, 11):
if number % 2 == 0:
continue
print(number)
遇到偶数时会执行 continue,所以后面的 print() 只会处理奇数。

在 while 循环中使用 continue 时,需要特别注意变量更新的位置:
python
number = 0
while number < 5:
number += 1
if number == 3:
continue
print(number)
这里先执行 number += 1,再判断是否跳过。如果把变量更新写在循环末尾,那么执行 continue 时可能跳过更新语句,最后形成无限循环。
九、循环中的 else
Python 的 for 和 while 都可以带有 else。当循环正常结束时,else 会执行;如果循环因为 break 提前结束,else 不会执行。
例如,查找一个数字:
python
numbers = [3, 8, 12, 19]
target = 10
for number in numbers:
if number == target:
print("已经找到")
break
else:
print("没有找到")
由于列表中没有 10,循环正常遍历结束,最后输出:
没有找到
如果把 target 改成 12,循环会执行 break,此时 else 不再执行。
这里的 else 对应的是 for,所以它的缩进需要和 for 保持一致:
python
for 元素 in 数据:
if 满足条件:
break
else:
没有通过 break 结束时执行

循环中的 else 并不是每段搜索代码都必须使用。如果增加一个布尔变量更容易理解,也可以使用普通写法:
python
found = False
for number in numbers:
if number == target:
found = True
break
if found:
print("已经找到")
else:
print("没有找到")
十、嵌套循环
一个循环里面还可以再写循环。外层循环每执行一次,内层循环都会完整执行一遍。
例如,输出一个简单的乘法表:
python
for row in range(1, 4):
for column in range(1, 4):
print(f"{row} × {column} = {row * column}")
print("---")
外层循环控制 row,内层循环控制 column。当 row 为 1 时,column 会依次取 1、2、3;接着 row 变成 2,内层循环重新从头开始。

1. break 只结束当前循环
在嵌套循环中,break 只会结束离它最近的那一层循环:
python
for row in range(1, 4):
for column in range(1, 4):
if column == 2:
break
print(row, column)
内层循环在 column == 2 时结束,但是外层循环仍然会继续处理下一行。
如果确实需要同时结束多层循环,可以设置一个状态变量,或者把循环放进函数中,再使用 return 返回。函数会在后面的章节中讲。
2. 不要写太深的嵌套
两层循环很常见,例如处理表格中的行和列。嵌套达到三四层以后,代码通常会变得难以阅读。遇到这种情况,可以检查数据结构是否合适,或者把一部分处理拆成函数。
十一、循环中的变量
Python 的 for 循环不会创建单独的块级作用域。循环结束以后,循环变量通常仍然可以访问:
python
for number in range(3):
print(number)
print("循环结束后的 number:", number)
输出结果为:
0
1
2
循环结束后的 number: 2
不过,不要依赖循环结束后保存的最后一个值。如果循环一次都没有执行,变量可能根本不存在:
python
for number in range(0):
print(number)
print(number) # NameError
需要在循环之后使用结果时,应该在循环前明确初始化变量。
十二、综合示例:统计多次输入
下面的程序接收多次成绩输入,输入 q 时结束,然后输出有效成绩的数量、总分和平均分:
python
count = 0
total = 0.0
while True:
text = input("请输入成绩,输入 q 结束:").strip()
if text == "q":
break
if not text:
print("输入不能为空")
continue
score = float(text)
if score < 0 or score > 100:
print("成绩应在 0 到 100 之间")
continue
total += score
count += 1
if count > 0:
average = total / count
print(f"共输入 {count} 个有效成绩")
print(f"总分:{total:.1f}")
print(f"平均分:{average:.1f}")
else:
print("没有输入有效成绩")
这个例子中,循环次数并不确定,所以使用 while True。输入 q 时通过 break 结束循环;空内容和超出范围的成绩通过 continue 跳过。循环结束以后,还需要先判断 count 是否大于 0,否则直接计算平均分会出现除零错误。
当前代码假设用户输入的是数字。如果输入 abc,float(text) 会出现 ValueError。异常处理会在后面的章节中单独讲。
十三、常见错误
1. 忘记更新 while 条件中的变量
python
number = 1
while number <= 5:
print(number)
这段代码会形成无限循环。需要在循环体中更新 number:
python
number += 1
2. 误以为 range() 包含终点
python
for number in range(1, 5):
print(number)
这里只会输出 1、2、3、4。需要输出到 5 时,终点应该写成 6。
3. 负步长和起止位置写反
python
for number in range(1, 5, -1):
print(number)
这段循环不会执行。步长为负数时,起点需要大于终点。
4. 在 continue 前漏掉变量更新
python
number = 0
while number < 5:
if number == 2:
continue
number += 1
当 number 变成 2 后,程序会一直执行 continue,再也没有机会更新 number。
5. 把 break 当成结束所有循环
嵌套循环中的 break 只结束当前层。需要结束外层循环时,不能只在内层写一个 break。
6. 修改正在遍历的数据
遍历列表时直接删除其中的元素,可能跳过部分内容:
python
numbers = [1, 2, 3, 4]
for number in numbers:
if number % 2 == 0:
numbers.remove(number)
对于这种需求,通常会遍历副本,或者生成一个新的列表。等学完列表以后再详细处理。
7. 循环嵌套过深
循环本身没有限制只能嵌套两层,但是层级越深,条件和变量越容易混淆。能够拆开的处理不要全部堆在一个循环中。
十四、练习
练习一:输出整数
使用 while 输出 1 到 20,再使用 for 和 range() 完成一次。
练习二:计算偶数和
计算 1 到 100 之间全部偶数的和。
练习三:倒计时
使用 range() 输出 10 到 1,最后输出 开始。
练习四:密码重试
预设一个密码,最多允许用户输入三次。输入正确时输出 登录成功 并结束循环;三次都不正确时输出 尝试次数已用完。
练习五:查找字符
接收一个字符串和一个目标字符,找到时输出它第一次出现的位置,没有找到时输出 字符不存在。可以使用 enumerate() 和循环中的 else。
练习六:九九乘法表
使用两层 for 循环输出九九乘法表。内层循环的终点需要根据外层循环当前的数字变化。
练习七:统计输入
不断接收整数,输入 0 时结束。最后输出正数、负数各有多少个,并计算所有非零数字的总和。
这一章讲完以后,已经可以使用循环重复处理数据,也可以通过 break 和 continue 改变循环的执行过程。下一章会开始学习列表和元组,包括元素访问、切片、增删改查以及列表复制。