Python 基础语法(四):循环结构与流程控制

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

思维导图

Python 中常用的循环有 whileforwhile 根据条件决定是否继续执行,for 用来依次取出一组数据中的每个元素。本章还会讲到 range()、嵌套循环、breakcontinue 和循环中的 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

这段代码的执行过程是:

  1. 先把 number 设置为 1
  2. 判断 number <= 5
  3. 条件成立,输出当前的 number
  4. 执行 number += 1
  5. 回到 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)

只在很短的计数循环中,才会经常使用 ij 这样的名称。循环变量完全不会被使用时,可以写成下划线 _

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)

输出 15。仍然需要注意,终点 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 以后,后面的 1924 不会再被检查。

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 的 forwhile 都可以带有 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。当 row1 时,column 会依次取 123;接着 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,否则直接计算平均分会出现除零错误。

当前代码假设用户输入的是数字。如果输入 abcfloat(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)

这里只会输出 1234。需要输出到 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,再使用 forrange() 完成一次。

练习二:计算偶数和

计算 1 到 100 之间全部偶数的和。

练习三:倒计时

使用 range() 输出 10 到 1,最后输出 开始

练习四:密码重试

预设一个密码,最多允许用户输入三次。输入正确时输出 登录成功 并结束循环;三次都不正确时输出 尝试次数已用完

练习五:查找字符

接收一个字符串和一个目标字符,找到时输出它第一次出现的位置,没有找到时输出 字符不存在。可以使用 enumerate() 和循环中的 else

练习六:九九乘法表

使用两层 for 循环输出九九乘法表。内层循环的终点需要根据外层循环当前的数字变化。

练习七:统计输入

不断接收整数,输入 0 时结束。最后输出正数、负数各有多少个,并计算所有非零数字的总和。

这一章讲完以后,已经可以使用循环重复处理数据,也可以通过 breakcontinue 改变循环的执行过程。下一章会开始学习列表和元组,包括元素访问、切片、增删改查以及列表复制。

相关推荐
卷无止境13 分钟前
Orca:当五个AI程序员同时给你打工
人工智能·python
OPEN-F13 分钟前
C++工程化:编译链接、调试与性能优化
开发语言·c++
邋遢道25 分钟前
# 企业级 Agent 从 0 到 1(三):推理循环——让模型自己决定停,它就停不下来
人工智能·python
坐吃山猪27 分钟前
【多线程】什么时候必须/推荐使用Thread类
java·开发语言
ZGG00327 分钟前
MCP 02:MCP 的各类比对——和 Function Calling、A2A、Skill 到底什么关系
人工智能·后端·python
dllmayday35 分钟前
基于python-can仿真生成blf
python
一只小阿乐36 分钟前
java 快速上手开发 2
java·开发语言·前端
张宇Joaquin40 分钟前
灵渠测试工具-urma_perftest
java·开发语言
Steve__evetS1 小时前
我的开源项目:python依赖安全修复助手
python·安全·agent