第 4 章 Python 控制流
在编程语言中,控制流(Control Flow) 指的是程序中语句的执行顺序。默认情况下,Python 程序会从上到下、逐行顺序执行代码。但在实际开发中,我们往往需要根据特定条件、循环逻辑或函数调用来动态改变程序的执行路径。
在 Python 中,控制流语句是构建逻辑结构的核心,它决定了程序的行为模式与执行逻辑。掌握控制流是从编写“代码”迈向编写“程序”的关键一步。
本章将系统介绍 Python 编程中的几类核心控制结构:
- 条件语句(If Statements) —— 让程序能根据不同条件执行不同代码分支,是实现逻辑判断的基础。
- 循环语句(For and While Loops) —— 通过重复执行某段代码,实现遍历数据结构或持续执行逻辑。
- 控制语句与辅助函数(pass、break、continue、range、zip、enumerate) —— 用于控制循环执行的细节,提高代码的灵活性与效率。
- 推导式与生成器(Comprehension and Generator) —— Python 的高阶特性,能在保持代码简洁的同时实现强大的数据处理能力。
通过本章的学习,读者将能够掌握 Python 控制程序流程的各种方式,为后续编写更复杂的逻辑与算法奠定坚实的基础。
1. if 语句
在 Python 中,if 语句 是最基本也是最重要的控制流结构之一。它用于实现程序的条件判断与决策操作——也就是说,程序会根据特定条件的真假,选择执行不同的代码块。
(1)基本语法结构
if 条件表达式:
语句块
当 if 后的条件表达式为 True 时,代码块中的语句将会执行;
如果条件为 False,则该代码块会被跳过。
例如:
if True:
print("This is so true.")
上面的代码中,括号内的判断条件是布尔值 True,因此 print() 语句会被执行,输出结果为:
This is so true.
在 Python 中,条件表达式不仅可以直接使用 True 或 False,还可以是任何能返回布尔值的表达式。
(2)条件判断的多种类型
if 语句的条件部分可以是多种类型的表达式,只要最终能返回布尔值即可。常见的包括:
① 比较运算符(Comparison Operators)。
用于比较两个值的大小关系,例如:
age = 18
if age >= 18:
print("You are an adult.")
输出结果为:
You are an adult.
常见比较运算符包括:==、!=、>、<、>=、<=
② 逻辑运算符(Logical Operators)。
用于组合多个判断条件,使逻辑更灵活,例如:
score = 85
if score > 80 and score < 90:
print("Good job!")
此时两个条件都为真,因此输出:
Good job!
常见逻辑运算符包括:and(与)、or(或)、not(非)
③ 真值与假值(Truthy and Falsy Values)。
在 Python 中,以下值会被视为 False:
- 数字
0 - 空字符串
"" - 空列表
[] - 空字典
{} None
其他非空、非零的值都会被视为 True。
例如:
name = ""
if name:
print("Hello,", name)
else:
print("Please enter your name.")
由于空字符串 "" 被视为 False,所以输出为:
Please enter your name.
(3)if–else 结构
if 语句还可以搭配 else,在条件不满足时执行另一段代码:
x = 10
if x > 0:
print("x is positive.")
else:
print("x is not positive.")
输出结果:
x is positive.
(4)if–elif–else 结构
当存在多个条件时,可以使用 elif(“else if”的缩写)实现多分支判断:
score = 75
if score >= 90:
print("Excellent")
elif score >= 70:
print("Good")
else:
print("Keep trying")
输出结果:
Good
if–elif–else 结构能帮助程序根据不同条件执行不同的逻辑,是实际开发中非常常见的控制结构。
2. match-case 语法
在 Python 3.10 及更高版本中,引入了一种全新的控制结构 —— match-case 语句。
它的功能类似于其他语言中的 switch-case,但语义更清晰、功能更强大,被称为 “结构化模式匹配(Structural Pattern Matching)”。
这一特性让代码在处理多分支逻辑时更加简洁,尤其适用于需要对不同数据结构进行分类处理的场景。
(1)基本语法结构。
match-case 的基本格式如下:
match variable:
case value1:
# 当 variable 等于 value1 时执行的代码
case value2:
# 当 variable 等于 value2 时执行的代码
case _:
# 默认分支,类似 else
其中:
match后面跟要匹配的变量;- 每个
case用于匹配特定的值; - 下划线
_表示“通配符”,匹配所有未被捕获的情况,相当于传统 switch 中的default。
(2)示例:匹配星期。
def get_weekday(day):
match day:
case 1:
return "Monday"
case 2:
return "Tuesday"
case 3:
return "Wednesday"
case 4:
return "Thursday"
case 5:
return "Friday"
case 6:
return "Saturday"
case 7:
return "Sunday"
case _:
return "Invalid day"
调用示例:
print(get_weekday(5))
输出结果:
Friday
✅ 这种写法比传统的 if–elif–else 更加清晰,尤其在需要匹配多个具体值时,结构更加整齐、可读性更强。
(3)支持复杂匹配模式
match-case 不仅可以匹配简单的值,还能匹配 序列、字典、类对象 等复杂结构。
例如:
def process_point(point):
match point:
case (0, 0):
print("Origin")
case (x, 0):
print(f"X-axis, x = {x}")
case (0, y):
print(f"Y-axis, y = {y}")
case (x, y):
print(f"Point ({x}, {y})")
调用示例:
process_point((0, 5))
输出结果:
Y-axis, y = 5
在此示例中,match 不仅判断了数值,还能直接解构元组中的变量,非常灵活。
(4)使用守卫条件(Guard)
有时我们希望在 case 中进一步添加条件判断,此时可以使用 if 守卫(if guard):
def describe_number(n):
match n:
case n if n < 0:
print("Negative number")
case n if n == 0:
print("Zero")
case n if n > 0:
print("Positive number")
调用示例:
describe_number(-8)
输出:
Negative number
守卫条件让 match-case 更加灵活,能实现类似 “条件过滤” 的效果。
3. for 循环与 while 循环
在程序设计中,循环(Loop) 是一种非常重要的控制结构,用于让一段代码重复执行多次。Python 提供了两种主要的循环方式:for 循环与 while 循环。虽然它们都能实现重复执行的效果,但适用的场景略有不同。
(1)for 循环(For Loop)
for 循环常用于遍历可迭代对象(Iterable),例如列表(list)、元组(tuple)、集合(set)、字符串(str)等。
换句话说,它会从可迭代对象中依次取出每个元素,然后执行相同的操作。
基本语法如下:
for 变量 in 可迭代对象:
执行语句
示例:
fruits = ["apple", "banana", "cherry"]
for f in fruits:
print(f)
输出结果:
apple
banana
cherry
✅ 每次循环中,变量 f 都会依次获取 fruits 列表中的一个元素,直到遍历结束。
for 循环的常见应用包括:
- 遍历列表、字典、字符串等结构;
- 与
range()搭配使用进行计数循环; - 批量执行某种逻辑(如批量打印、计算、过滤数据等)。
示例:
for i in range(5):
print("Number:", i)
输出:
Number: 0
Number: 1
Number: 2
Number: 3
Number: 4
这里 range(5) 生成从 0 到 4 的整数序列(不包括 5),因此循环执行 5 次。
(2)while 循环(While Loop)
while 循环用于在**条件为真(True)**时,反复执行指定的代码块。
一旦条件为假(False),循环就会立即结束,程序继续执行后续的语句。
基本语法如下:
while 条件表达式:
执行语句
示例:
count = 0
while count < 3:
print("Counting:", count)
count += 1
输出结果:
Counting: 0
Counting: 1
Counting: 2
✅ 循环会在 count < 3 成立时持续执行。
当 count 自增到 3 时,条件为假,循环结束。
⚠️ 注意:
如果 while 条件永远为真(True),则会产生无限循环(infinite loop),程序将无法自动停止。
例如:
while True:
print("This will run forever!")
在实际开发中,必须确保循环体中存在能使条件变化的语句(例如自增变量、用户输入等),否则程序可能陷入死循环。
(3)for 与 while 的选择原则
|
使用场景 |
推荐循环类型 |
示例 |
|
明确知道循环次数时 |
✅ for 循环 |
遍历列表、执行固定次数的操作 |
|
循环次数未知,取决于条件是否满足 |
✅ while 循环 |
等待用户输入、检测系统状态等 |
简而言之:
- for 循环 → 适合“已知次数”的任务
- while 循环 → 适合“基于条件”的任务
(4)for 与 while 的结合使用示例
有时两者可以配合使用:
numbers = [1, 3, 5, 7, 9]
i = 0
while i < len(numbers):
print("Current number:", numbers[i])
i += 1
与下方的 for 循环效果完全相同:
for n in numbers:
print("Current number:", n)
两种写法都能实现相同逻辑,选择哪一种主要取决于代码的意图与风格。
通过灵活使用 for 与 while 循环,我们可以让程序高效地处理重复任务,提升自动化与逻辑控制的能力。
4. 嵌套循环(Nested Loops)
在 Python 中,我们不仅可以编写单层循环,还可以在一个循环内部再嵌套另一个循环,这种结构就称为 嵌套循环(Nested Loop)。
嵌套循环常用于处理二维数据结构(例如列表嵌套列表)、打印图形模式、矩阵运算等场景,是编程中非常重要的逻辑结构。
(1)什么是嵌套循环?
嵌套循环指的是在外部循环(Outer Loop)的循环体内,再包含一个内部循环(Inner Loop)。
每当外部循环执行一次,内部循环就会被完整地执行一遍。
语法结构如下:
for 外部变量 in 外部序列:
for 内部变量 in 内部序列:
执行语句
或使用 while:
while 条件1:
while 条件2:
执行语句
(2)基本示例
来看一个简单的例子:
for i in range(3): # 外部循环
for j in range(2): # 内部循环
print(f"i={i}, j={j}")
输出结果:
i=0, j=0
i=0, j=1
i=1, j=0
i=1, j=1
i=2, j=0
i=2, j=1
✅ 可以看到:每当外层循环变量 i 取一个新值时,内层循环 j 都会从头执行一次。
运行机制:
- 外层循环执行第 1 次时,内层循环执行完整的 2 次;
- 外层循环执行第 2 次时,内层循环再次完整执行;
- 如此往复,直到外层循环条件不再满足。
(3)嵌套循环的应用场景
① 输出乘法表。
嵌套循环最常见的例子之一是打印 九九乘法表:
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j}", end="\t")
print()
输出结果:
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
...
这里外层循环控制行数(从 1 到 9),内层循环控制每行输出的乘法表达式。
② 遍历二维列表(矩阵)。
如果我们有一个二维列表(即列表嵌套列表),嵌套循环可以方便地访问每个元素:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for row in matrix:
for item in row:
print(item, end=" ")
print()
输出结果:
1 2 3
4 5 6
7 8 9
外层循环遍历“行”,内层循环遍历“列”,这种结构在数据分析与图像处理场景中非常常见。
(4)嵌套循环的性能与优化
虽然嵌套循环功能强大,但要注意性能问题。
当外层循环执行 m 次,内层循环执行 n 次时,总执行次数为 m × n。
例如:
for i in range(1000):
for j in range(1000):
pass
此循环将执行 1,000 × 1,000 = 1,000,000 次!
因此,在处理大量数据时,应谨慎使用多层嵌套循环。可以考虑以下优化策略:
- 使用 列表推导式 替代部分嵌套循环;
- 使用 break / continue 提前结束不必要的循环;
- 借助 NumPy 等科学计算库 进行批量运算以提升效率。
5. Pass 语句
pass 语句顾名思义——“什么都不做”。它是 Python 中的占位语句(placeholder statement),在语法上需要有一条语句,但程序逻辑上暂时没有实际操作时使用。
换句话说,pass 不会执行任何命令或产生任何结果,只是为了让代码在语法上保持完整,从而避免报错。
例如,在 Python 中,某些结构(如 if、for、while、def、class)后面必须跟随一个语句块。如果我们暂时不想编写具体逻辑,可以先用 pass 语句占位:
if True:
pass # 什么都不做,但语法正确
else:
print("This will not execute.")
上面的代码不会输出任何结果,因为 pass 不执行任何操作。
典型使用场景:
① 占位符:在函数、类、循环或条件语句中提前搭建代码结构,等待后续补充逻辑。
def future_function():
pass # 以后再实现
② 空循环结构:在循环中不执行任何操作,仅用于维持语法完整。
for _ in range(5):
pass # 占位循环
③ 调试阶段的临时代码:在删除部分逻辑但不想破坏代码结构时,使用 pass 替代被移除的语句。
6. break 语句
break 语句用于立即终止它所在的循环或语句块的执行。
当程序在循环中遇到 break 时,会立刻跳出当前循环体,并将程序控制权转移到循环之后的第一条语句处继续执行。
for i in range(5):
if i == 3:
break # 当 i 等于 3 时跳出循环
print(i)
print("循环结束")
输出结果:
0
1
2
循环结束
可以看到,当循环变量 i 的值为 3 时,break 被触发,循环提前终止,后续的 print(i) 语句不再执行。
(1)使用场景
① 提前结束循环:当满足特定条件时,不再继续执行剩余的循环。
② 在查找操作中中断:当在数据集合中找到目标项后,可以使用 break 停止搜索,从而提高效率。
for name in ["Alice", "Bob", "Charlie", "David"]:
if name == "Charlie":
print("找到目标,结束循环!")
break
(2)嵌套循环中的行为
如果 break 位于嵌套循环(即循环中套循环)中,它只会终止所在的那一层循环,外层循环仍然会继续执行。
for i in range(3): # 外层循环
for j in range(3): # 内层循环
if j == 1:
break # 只终止内层循环
print(i, j)
输出结果:
0 0
1 0
2 0
内层循环在 j == 1 时退出,但外层循环 i 仍继续迭代。
7. continue 语句
continue 语句与 break 一样,属于循环控制语句,但二者的行为截然不同。break 是立即终止整个循环,而 continue 则是跳过当前循环的剩余语句,直接开始下一次循环迭代。
(1)基本用法
当循环执行到 continue 时,Python 会跳过它之后的所有语句,不再执行本轮循环中余下的部分,然后立刻回到循环开头,判断下一次迭代条件。
for i in range(5):
if i == 2:
continue # 当 i 等于 2 时,跳过本轮循环
print(i)
输出结果:
0
1
3
4
可以看到,i == 2 时的循环被跳过,print(i) 未执行,但循环整体仍然继续进行。
(2)在 while 循环中的应用
continue 同样可用于 while 循环中,用于控制循环逻辑,使代码更加简洁。
count = 0
while count < 5:
count += 1
if count == 3:
continue
print(count)
输出结果:
1
2
4
5
当 count == 3 时,continue 跳过本次循环,未执行 print(count)。
(3)与 break 的区别
|
特性 |
break |
continue |
|
功能 |
终止整个循环 |
跳过当前迭代,继续下一次循环 |
|
执行后结果 |
程序控制流转移到循环外部 |
程序控制流回到循环起始处 |
|
常见用途 |
满足条件后提前退出 |
跳过不符合条件的某些项 |
(4)嵌套循环中的作用
与 break 一样,continue 只影响它所在的循环层级,不会作用到外层循环。
for i in range(3):
for j in range(3):
if j == 1:
continue # 跳过当前内层循环中的 j==1
print(i, j)
输出结果:
0 0
0 2
1 0
1 2
2 0
2 2
8. range() 函数
range() 是 Python 中最常用的内置函数之一,用于生成一个整数序列。
在循环语句(尤其是 for 循环)中,range() 的使用频率非常高,因为它能方便地控制循环次数和循环范围。
(1)基本语法
range(start, stop, step)
|
参数 |
说明 |
|
start |
可选参数,序列的起始整数,默认为 0。 |
|
stop |
必选参数,序列的结束整数(不包含该值)。 |
|
step |
可选参数,序列的步长,默认为 1。 |
(2)基本示例
for i in range(5):
print(i)
输出结果:
0
1
2
3
4
这里 range(5) 表示从 0 开始到 5(不包括 5),即 [0, 1, 2, 3, 4]。
(3)指定起点与终点
for i in range(2, 7):
print(i)
输出结果:
2
3
4
5
6
此时,循环从 2 开始,到 7 之前结束。
(3)设置步长
步长(step)用于指定数字之间的间隔,可以是正数或负数。
for i in range(1, 10, 2):
print(i)
输出结果:
1
3
5
7
9
这里的 2 表示每次增加 2。
若要生成递减序列,可以使用负步长:
for i in range(10, 0, -2):
print(i)
输出结果:
10
8
6
4
2
(4)为什么要使用 range()?
在 Python 2 中,range(n) 会返回一个完整的列表,例如:
range(5) # 返回 [0, 1, 2, 3, 4]
这意味着所有数字都会被一次性创建并存储在内存中。对于小规模数据影响不大,但当 n 很大时,例如 range(1000000),就会占用大量内存。
而在 Python 3 中,range() 返回的是一个 range 对象,它是一种惰性序列(lazy sequence),不会一次性生成所有数字,而是在循环时动态创建当前所需的值。
这意味着:
- 无论范围多大,
range()都只会占用极少的内存; - 计算速度更快,性能更高;
- 特别适合用于循环控制或大数据场景。
(5)验证 range 对象的类型
r = range(5)
print(type(r))
输出结果:
<class 'range'>
这说明 range() 返回的是一个 range 对象,而不是列表。
(6)转换为列表
如果确实需要查看或操作完整的序列,可以使用 list() 将 range 对象转换为列表:
r = range(5)
print(list(r))
输出结果:
[0, 1, 2, 3, 4]
9. enumerate () 与 zip () 函数
在 Python 中,enumerate() 函数可以为可迭代对象添加一个计数器,并将计数器与元素组合成包含两个元素的元组。这样,在遍历列表、元组或其他可迭代对象时,就可以方便地跟踪当前迭代到第几个元素。
例如:
fruits = ['苹果', '香蕉', '橙子']
for index, fruit in enumerate(fruits):
print(index, fruit)
运行结果为:
0 苹果
1 香蕉
2 橙子
可以看到,每个元素前面都有一个对应的索引值。
另一方面,zip() 函数可以将多个可迭代对象“打包”在一起,生成一个元组的迭代器。zip() 会把相同位置的元素组合成一个元组,从而方便同时遍历多个序列。
例如:
names = ['Alice', 'Bob', 'Charlie']
scores = [90, 85, 92]
for name, score in zip(names, scores):
print(name, score)
运行结果为:
Alice 90
Bob 85
Charlie 92
这里,zip() 把 names 和 scores 中对应位置的元素组合在一起,方便我们在循环中同时获取两个列表的值。
总结来说,enumerate() 用于“给元素加索引”,而 zip() 用于“将多个序列组合”,都是在循环遍历时非常实用的工具。
10. 推导式(Comprehension)
在 Python 中,推导式(Comprehension) 提供了一种简洁高效的方式,用已有的序列来生成新的序列,比如列表、集合或字典等。使用推导式,可以用更少的代码完成复杂的循环和条件操作,使代码更清晰、更“Python 风格”(Pythonic)。
Python 支持四种常见的推导式:
- 列表推导式(List Comprehensions)
用于生成新的列表,通过循环和条件语句快速构建列表。 - 字典推导式(Dictionary Comprehensions)
用于生成字典,可以通过映射已有序列中的元素来创建键值对。 - 集合推导式(Set Comprehensions)
用于生成集合,会自动去重,并支持循环与条件过滤。 - 生成器推导式(Generator Comprehensions)
返回一个生成器对象,按需生成元素,节省内存,适合处理大数据量。
推导式的使用非常普遍,是 Python 程序员编写简洁、优雅代码的重要手段。
11. 列表推导式(List Comprehensions)
列表推导式是一种简洁的方法,用已有的列表生成新的列表。它的通用语法如下:
new_list = [运算操作 for 变量 in 原始列表 if 条件]
其中,“运算操作”用于对每个元素进行处理,“变量”表示列表中的每个元素,“条件”是可选的筛选条件。
举个简单的例子:
x = [1, 2, 3, 4]
squared_x = [item ** 2 for item in x]
print(squared_x)
运行结果为:
[1, 4, 9, 16]
在这个例子中,我们使用列表推导式将列表 x 中的每个元素平方后生成了一个新的列表 squared_x。
列表推导式的优势在于,它能够用一行代码完成传统循环中多行才能实现的操作,使代码更加简洁和“Python 风格”。
12. 字典推导式(Dictionary Comprehensions)
字典推导式是一种快速生成字典的方法,可以通过已有序列或字典创建新的字典。它的通用语法如下:
new_dict = {键: 值(运算操作) for 变量 in 原始序列 if 条件}
其中,“键”表示新字典的键,“值”是对元素进行运算后的结果,“变量”表示序列中的每个元素,“条件”是可选的筛选条件。
举个例子:
x = [1, 2, 3, 4]
x_squared_dict = {item: item ** 2 for item in x if item > 2}
print(x_squared_dict)
运行结果为:
{3: 9, 4: 16}
在这个例子中,我们使用字典推导式,将列表 x 中大于 2 的元素作为键,对应的平方作为值,生成了一个新的字典 x_squared_dict。
字典推导式能够用简洁的方式完成原本需要多行循环和条件判断才能实现的操作,使代码更紧凑、易读。
13. 集合推导式(Set Comprehensions)
集合推导式用于通过已有序列快速生成新的集合。它的通用语法如下:
new_set = {运算操作 for 变量 in 原始序列 if 条件}
其中,“运算操作”表示对每个元素的处理方式,“变量”表示序列中的元素,“条件”是可选的筛选条件。
举个例子:
x = [1, 2, 3, 4]
x_squared_set = {item ** 2 for item in x if item > 2}
print(x_squared_set)
运行结果为:
{16, 9}
在这个例子中,我们使用集合推导式,将列表 x 中大于 2 的元素平方后生成一个新的集合 x_squared_set。
集合推导式的特点是自动去重,即使原序列中有重复元素,生成的集合也只会保留唯一值。通过集合推导式,可以用简洁的语法完成原本需要多行循环和判断才能实现的操作,使代码更紧凑且 Python 风格明显。
14. 生成器推导式(Generator Comprehensions)
生成器推导式的语法与列表推导式非常相似,只是将方括号 [] 换成了圆括号 ()。与列表推导式不同,生成器推导式返回的是一个 生成器对象,而不是完整的列表。
例如:
x = [1, 2, 3, 4]
gen = (item ** 2 for item in x if item > 2)
print(gen)
运行结果为:
<generator object <genexpr> at 0x...>
可以通过 for 循环或 next() 函数逐个取出生成器中的元素:
for value in gen:
print(value)
输出结果为:
9
16
生成器的优势在于 按需生成元素,不会一次性占用大量内存,因此在处理大数据量时比列表推导式更加高效。这一点与 range() 函数的内存优化原理类似。
需要注意的是,Python 中没有元组推导式。原因是推导式的工作机制是将循环或迭代得到的元素依次分配到一个容器中,而元组是不可变对象,无法接收赋值操作,因此不支持推导式语法。
15. 编程练习:实现 wc 功能
wc(word count 的缩写)是 Unix 及类 Unix 系统中的命令,用于统计文件的行数、单词数和字节数。下面我们用 Python 编写一个简化版程序,实现类似功能:
import sys
# 检查命令行参数
if len(sys.argv) != 2:
print("用法: python wc.py 文件名")
sys.exit(1)
filename = sys.argv[1]
# 初始化计数器
lines = 0
words = 0
chars = 0
# 打开文件并逐行处理
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
lines += 1 # 行数累加
words += len(line.split()) # 单词数累加
chars += len(line) # 字符数累加
# 打印统计结果
print(f"行数: {lines}")
print(f"单词数: {words}")
print(f"字符数: {chars}")
运行示例:
python wc.py example.txt
输出示例:
行数: 10
单词数: 56
字符数: 345
说明:
- 使用
open()打开文件,并通过for line in f逐行读取。 - 使用
split()方法按空格分割每行,统计单词数。 - 使用
len()分别统计行数、单词数和字符数。 - 通过
sys.argv获取命令行传入的文件名,实现对不同文件的统计。
更多推荐

所有评论(0)