Python 作为一种简洁而功能强大的编程语言,其控制流结构是程序逻辑的核心组成部分。本文将系统地介绍 Python 中的基础控制流机制,包括条件判断、循环遍历、循环控制以及 Python 3.10+ 引入的模式匹配语句,帮助读者全面掌握 Python 的控制流特性,理解它们的语法结构、应用场景和最佳实践。

1. 条件判断语句

条件判断是编程中最基本的控制流结构之一,它允许程序根据特定条件执行不同的代码块。

1.1 基本语法

if-elif-else 语句的基本语法结构如下:

1
2
3
4
5
6
if 条件表达式1:
# 条件表达式1为True时执行的代码块
elif 条件表达式2:
# 条件表达式2为True时执行的代码块
else:
# 所有条件表达式都不为True时执行的代码块

其中:

  • if关键字后跟一个条件表达式,如果该表达式为真,则执行其下的代码块
  • elif是”else if”的缩写,用于在前一个条件不满足时检查另一个条件
  • else关键字定义了当所有条件都不满足时的默认执行路径
  • 每个条件块后必须有缩进,Python 使用缩进作为代码块的标识

1.2 逻辑表达式与运算符

条件判断的表达式可以是任何返回布尔值的表达式,常用的逻辑运算符包括:

运算符 功能 示例
== 等于 5 == 5 → True
!= 不等于 5 != 3 → True
> 大于 5 > 3 → True
< 小于 5 < 3 → False
>= 大于等于 5 >= 5 → True
<= 小于等于 5 <= 3 → False
and 逻辑与 (x > 0) and (y < 10)
or 逻辑或 (x == 0) or (y == 0)
not 逻辑非 not (x is None)

多条件组合是 if-elif-else 语句的典型应用场景。

  • 例如,检查一个数是正数、负数还是零:
1
2
3
4
5
6
7
8
num = 15

if num > 0:
print(f"{num} 是正数")
elif num < 0:
print(f"{num} 是负数")
else:
print(f"{num} 是零")

1.3 字符串比较与多条件判断

Python 中的字符串比较是基于字典序的,这在处理文本数据时非常有用:

1
2
3
4
5
6
7
8
command = "start"

if command == "start":
print("✅ 系统已启动")
elif command == "stop":
print("❌ 系统已停止")
else:
print("⚠ 未知命令")

多条件判断可以结合多个变量或表达式,使用逻辑运算符连接:

1
2
3
4
5
6
7
8
9
age = 18
is_student = True

if age >= 18 and not is_student:
print("您已成年且不是学生,可进入网吧")
elif age < 18:
print("您未成年,无法进入网吧")
else:
print("您是学生,享受学生优惠")

1.4 复杂条件的组织📚

当条件变得复杂时,可以考虑使用括号来提高可读性:

1
2
3
4
if (score >= 90 and attendance >= 80) or (score >= 95):
print("授予优秀学生奖")
else:
print("常规评价")

此外,也可以将条件判断封装成函数,提高代码的可维护性:

1
2
3
4
5
6
7
8
9
def is_valid_user(user):
return user.age >= 18 and user.is_active and not user.is_banned

user = User(age=25, is_active=True, is_banned=False)

if is_valid_user(user):
print("允许访问受限内容")
else:
print("访问受限")

2. 循环遍历

循环遍历允许程序重复执行一段代码,直到满足特定终止条件。Python 中最常用的循环结构是 for 循环,它基于迭代器协议工作。

2.1 for 循环基本语法

for 循环的基本语法结构如下:

1
2
for 变量 in 可迭代对象:
# 循环体代码块

其中:

  • 变量会依次接收可迭代对象中的每一个元素
  • 可迭代对象可以是列表、元组、字符串、字典、集合或任何实现了迭代器协议的对象
  • 循环体代码块必须缩进

遍历字符串示例:

1
2
3
4
text = "Python"

for char in text:
print(char) # 依次打印每个字符:P, y, t, h, o, n

遍历列表示例:

1
2
3
4
fruits = ["苹果", "香蕉", "橙子", "葡萄"]

for fruit in fruits:
print(f"我喜欢吃{fruit}")

2.2 range() 函数详解📚

range() 函数是 Python 中生成整数序列的强大工具,其语法为:

1
range([start], stop[, step])

其中:

  • start:起始值(可选,默认为0)
  • stop:结束值(不包含该值)
  • step:步长(可选,默认为1)

简单范围示例:

1
2
for i in range(5):
print(i) # 输出0, 1, 2, 3, 4

指定起始值示例:

1
2
for i in range(2, 6):
print(i) # 输出2, 3, 4, 5

指定步长示例:

1
2
for i in range(1, 10, 2):
print(i) # 输出1, 3, 5, 7, 9

2.3 循环嵌套

循环嵌套是指在一个循环体内再嵌套另一个循环,常用于处理二维数据结构:

1
2
3
4
5
# 九九乘法表示例
for i in range(1, 10):
for j in range(1, i+1):
print(f"{j}×{i}={i*j}", end="") # end="" 使输出对齐
print() # 每行结束后换行

2.4 循环中的常见应用

for 循环常用于以下场景:

  1. 批量数据处理:遍历文件中的每一行
  2. 索引访问:结合枚举获取元素及其索引
  3. 迭代字典:访问字典的键、值或项

遍历文件示例:

1
2
3
with open("data.txt", "r") as file:
for line in file:
print(line.strip()) # 去除换行符后打印每一行

枚举索引示例:

1
2
3
4
fruits = ["苹果", "香蕉", "橙子", "葡萄"]

for index, fruit in enumerate(fruits):
print(f"索引 {index} 对应的水果是 {fruit}")

字典遍历示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
person = {"name": "张三", "age": 30, "city": "北京"}

# 遍历键
for key in person:
print(f"键: {key}")

# 遍历值
for value in person.values():
print(f"值: {value}")

# 遍历键值对
for key, value in person.items():
print(f"{key}: {value}")

3. 循环控制📚

在循环过程中,有时需要根据特定条件控制循环的执行流程,Python 提供了三种控制循环的语句:break、continue 和 pass。

3.1 break语句

  • break语句:终止循环
    break 语句用于立即终止当前所在的循环,跳出循环体:
1
2
3
4
5
6
7
8
# 示例:查找列表中第一个偶数
numbers = [1, 3, 5, 8, 9, 12]

for num in numbers:
if num % 2 == 0:
print(f"找到第一个偶数: {num}")
break # 找到后立即终止循环
print(f"{num} 是奇数")

嵌套循环中,break 只能终止最内层的循环:

1
2
3
4
5
6
7
# 示例:嵌套循环中的break
for i in range(2, 6):
for j in range(i):
if j == 1:
break # 只会终止内层循环
print(j, end=" ")
print()

输出结果为:

1
2
3
4
0
0
0
0

如果需要在嵌套循环中实现多层跳出,可以使用标志变量:

1
2
3
4
5
6
7
8
9
10
11
# 示例:使用标志变量实现多层循环跳出
found = False

for row in matrix:
for element in row:
if element == target:
print(f"找到目标值 {target}")
found = True
break # 跳出内层循环
if found:
break # 跳出外层循环

3.2 continue 语句

continue 语句:跳过当前迭代
continue 语句用于跳过当前循环迭代,立即进入下一次循环迭代:

1
2
3
4
5
6
7
# 示例:跳过奇数
numbers = [1, 2, 3, 4, 5, 6]

for num in numbers:
if num % 2 != 0:
continue # 跳过奇数
print(f"{num} 是偶数")

数据过滤是 continue 的典型应用场景:

1
2
3
4
5
6
7
# 示例:处理混合数据类型,仅处理整数
mixed_data = [12, "hello", 45, "world", 78, "python"]

for item in mixed_data:
if not isinstance(item, int):
continue # 跳过非整数类型
print(f"处理整数: {item}")

处理空值或无效数据时,continue也很有用:

1
2
3
4
5
6
7
# 示例:跳过空字符串和无效条目
inputs = ["Alice", "", "Bob", " ", "Charlie"]

for name in inputs:
if not name.strip(): # 跳过空字符串或仅包含空格的字符串
continue
print(f"有效用户名: {name}")

3.3 pass 语句

pass 语句:空操作占位符
pass 语句是一个空操作语句,它不执行任何操作,但可以用于语法上需要语句而暂时不需要执行任何代码的场景:

1
2
3
# 示例:占位符,暂时不处理
for item in some_list:
pass # 未来会添加处理逻辑

pass 在循环中的主要用途是:

  1. 占位符:在编写框架代码时,为将来实现的逻辑预留位置
  2. 调试辅助:临时禁用某些代码块,而不必删除它们
  3. 语法结构保持:某些情况下必须有代码块,但暂时不需要任何操作

4. 模式匹配初探📚

  • 模式匹配初探:match-case 语句
    Python 3.10 引入了结构化模式匹配(Structural Pattern Matching)语法,即 match-case 语句,它提供了一种比传统 if-elif-else 更强大、更直观的条件分支机制。

4.1 match-case 基础语法

match-case 语句的基本语法结构如下:

1
2
3
4
5
6
7
match subject:
case pattern1:
# 匹配pattern1时的代码块
case pattern2 if condition:
# 匹配pattern2且满足condition时的代码块
case _:
# 默认情况的代码块

其中:

  • subject是匹配的对象,可以是任何值
  • pattern是模式,可以是字面量、变量、类型、结构或组合模式
  • if condition是可选的守卫条件,用于进一步过滤匹配
  • _是通配符,匹配任何未匹配的值

4.2 基本匹配模式

4.2.1 字面量匹配

可以直接匹配具体的字面量值:

1
2
3
4
5
6
7
8
9
10
# 示例:匹配命令字符串
command = "stop"

match command:
case "start":
print("系统已启动")
case "stop":
print("系统已停止")
case _:
print(f"未知命令: {command}")

4.2.2 类型匹配

可以匹配值的类型:

1
2
3
4
5
6
7
8
9
10
11
12
# 示例:匹配不同类型
data = 42.5

match data:
case int():
print("这是一个整数")
case float():
print("这是一个浮点数")
case str():
print("这是一个字符串")
case _:
print("未知类型")

4.2.3 序列匹配

可以匹配列表、元组等序列的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 示例:匹配元组坐标
def analyze_point(point):
match point:
case (0, 0):
print("原点")
case (0, y):
print(f"Y轴上的点,坐标为 {y}")
case (x, 0):
print(f"X轴上的点,坐标为 {x}")
case (x, y):
print(f"点坐标为 ({x}, {y})")
case _:
print("不是点的格式")

analyze_point((0, 0)) # 输出:原点
analyze_point((0, 5)) # 输出:Y轴上的点,坐标为 5
analyze_point((3, 0)) # 输出:X轴上的点,坐标为 3
analyze_point((2, 3)) # 输出:点坐标为 (2, 3)
analyze_point("invalid") # 输出:不是点的格式

4.2.4 字典匹配

可以匹配字典的键值对结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 示例:匹配字典结构
def process_transaction(tx):
match tx:
case {"type": "deposit", "amount": amt} if amt > 0:
print(f"💰 存入 {amt} 元")
case {"type": "withdraw", "amount": amt, "balance": bal} if amt <= bal:
print(f"💸 取出 {amt} 元")
case {"type": "withdraw", "amount": amt}:
print(f"❌ 取款失败,金额 {amt} 超出余额")
case {"type": _}:
print("⚠ 无效交易类型")
case _:
print("⚠ 无效交易格式")

process_transaction({"type": "deposit", "amount": 100}) # 输出:💰 存入 100 元
process_transaction({"type": "withdraw", "amount": 50, "balance": 100}) # 输出:💸 取出 50 元
process_transaction({"type": "withdraw", "amount": 200, "balance": 100}) # 输出:❌ 取款失败,金额 200 超出余额

4.2.5 变量捕获

可以在模式中捕获匹配的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 示例:捕获匹配的值
def handle_data(data):
match data:
case int(n) if n % 2 == 0:
print(f"数码: {n} 是偶数")
case float(f) if f > 100.0:
print(f"大额浮点数: {f:.2f}")
case str(s) if len(s) > 50:
print(f"长文本(已截断): {s[:50]}...")
case list([int(x), *rest]):
print(f"整数列表,首元素: {x}, 长度: {len(rest)+1}")
case _:
print(f"未知数据类型: {type(data).__name__}")

handle_data(42) # 输出:数码: 42 是偶数
handle_data(150.75) # 输出:大额浮点数: 150.75
handle_data("这是一个超过50个字符的长文本示例,用于测试长文本截断功能") # 输出:长文本(已截断): 这是一个超过50个字符的长文本示例,用于测试...
handle_data([10, 20, 30]) # 输出:整数列表,首元素: 10, 长度: 3
handle_data({"key": "value"}) # 输出:未知数据类型: dict

4.3 高级匹配模式

4.3.1 多模式匹配

可以使用|运算符匹配多个值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 示例:匹配多个值
def get_day_type(day):
match day:
case "Monday" | "Tuesday" | "Wednesday" | "Thursday":
return "工作日"
case "Friday":
return "周五(可能为休息日)"
case "Saturday" | "Sunday":
return "周末"
case _:
return "无效日期"

print(get_day_type("Monday")) # 输出:工作日
print(get_day_type("Friday")) # 输出:周五(可能为休息日)
print(get_day_type("Sunday")) # 输出:周末
print(get_day_type("XX")) # 输出:无效日期

4.3.2 守卫条件

可以在 case 语句中添加条件判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 示例:带守卫条件的匹配
def analyze_number(n):
match n:
case 0:
print("零")
case x if x > 0:
print(f"正数: {x}")
case x if x < 0:
print(f"负数: {x}")
case _:
print("无法识别的数值")

analyze_number(0) # 输出:零
analyze_number(42) # 输出:正数: 42
analyze_number(-7) # 输出:负数: -7
analyze_number("abc") # 输出:无法识别的数值

4.3.3 序列模式

可以匹配序列的结构,包括列表和元组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 示例:匹配序列模式
def process_sequence(seq):
match seq:
case []: # 空序列
print("空列表")
case [a]: # 单元素序列
print(f"单元素列表: {a}")
case [a, b]: # 双元素序列
print(f"双元素列表: {a}, {b}")
case [a, b, c]: # 三元素序列
print(f"三元素列表: {a}, {b}, {c}")
case [a, *rest]: # 首元素后跟多个元素
print(f"首元素为 {a},其余元素为 {rest}")
case _:
print(f"未知数据类型: {type(seq).__name__}")

process_sequence([]) # 输出:空列表
process_sequence([1]) # 输出:单元素列表: 1
process_sequence([1, 2]) # 输出:双元素列表: 1, 2
process_sequence([1, 2, 3]) # 输出:三元素列表: 1, 2, 3
process_sequence([1, 2, 3, 4]) # 输出:首元素为 1,其余元素为 [2, 3, 4]
process_sequence((1, 2, 3)) # 输出:三元素列表: 1, 2, 3
process_sequence("hello") # 输出:未知数据类型: str

4.3.4 类实例匹配

可以匹配自定义类的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 示例:匹配类实例
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

person = Person("张三", 30)

match person:
case Person("李四", age) if age < 20:
print(f"青少年李四,年龄 {age}")
case Person("李四", _):
print("成年人李四")
case Person(name, age) if age >= 60:
print(f"老年人: {name}")
case Person(name, age):
print(f"名字是 {name},年龄 {age}")
case _:
print("未知对象")

# 输出:名字是 张三,年龄 30

4.3.5 as 子句

使用as子句可以捕获匹配的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 示例:使用as子句捕获匹配值
def check_value(value):
match value:
case int() as n:
print(f"整数: {n}")
case float() as f:
print(f"浮点数: {f}")
case str() as s:
print(f"字符串: {s}")
case _:
print(f"未知类型: {type(value).__name__}")

check_value(42) # 输出:整数: 42
check_value(3.14) # 输出:浮点数: 3.14
check_value("hello") # 输出:字符串: hello
check_value([1, 2, 3]) # 输出:未知类型: list

4.4 match-case 的适用场景

match-case 语句特别适合以下场景

  1. 处理结构化数据:如字典、元组、列表等数据结构
  2. 类型匹配与转换:根据值的类型执行不同操作
  3. 多模式组合:同时匹配多个可能的值或模式
  4. 数据解构:从复杂数据结构中提取特定部分
  5. 状态机实现:处理不同状态下的行为

与 if-elif-else 相比的优势

  • 代码更清晰:通过模式直接描述匹配条件,可读性更高
  • 结构更直观:每个 case 对应一个模式,避免深层嵌套
  • 类型安全:可以明确指定类型和结构,减少运行时错误
  • 性能优化:Python 3.12+ 对 match-case 进行了性能优化,执行效率更高

5. if-elif-else 与 match-case📚

5.1 适用场景对比

特性 if-elif-else match-case
简单值比较 简洁直观 需使用字面量模式,稍显冗余
动态条件判断 支持任意逻辑表达式 需通过守卫条件实现,灵活性稍低
数据结构匹配 需手动解构,代码冗长 直接支持结构匹配,代码简洁
类型匹配 需使用isinstance等函数 直接支持类型模式,代码直观
多模式组合 需多个elif分支 使用|运算符,代码更紧凑
性能 Python 3.10-3.11性能稳定 Python 3.12+性能优化,执行效率更高

5.2 代码结构对比

5.2.1 处理命令字符串

使用 if-elif-else:

1
2
3
4
5
6
7
8
command = "stop"

if command == "start":
print("系统已启动")
elif command == "stop":
print("系统已停止")
else:
print(f"未知命令: {command}")

使用 match-case:

1
2
3
4
5
6
7
8
9
command = "stop"

match command:
case "start":
print("系统已启动")
case "stop":
print("系统已停止")
case _:
print(f"未知命令: {command}")

5.2.2 处理数据结构

使用 if-elif-else:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def process_data(data):
if isinstance(data, int):
print(f"整数: {data}")
elif isinstance(data, str):
print(f"字符串: {data}")
elif isinstance(data, list) and len(data) == 2:
x, y = data
print(f"二维列表: ({x}, {y})")
elif isinstance(data, list):
print(f"列表,长度: {len(data)}")
else:
print("未知类型")

process_data(42) # 整数: 42
process_data("Hello") # 字符串: Hello
process_data([1, 2]) # 二维列表: (1, 2)
process_data([1, 2, 3]) # 列表,长度: 3
process_data({"key": "value"})

使用 match-case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def process_data(data):
match data:
case int():
print(f"整数: {data}")
case str():
print(f"字符串: {data}")
case [x, y]:
print(f"二维列表: ({x}, {y})")
case list():
print(f"列表,长度: {len(data)}")
case _:
print("未知类型")

process_data(42) # 整数: 42
process_data("Hello") # 字符串: Hello
process_data([1, 2]) # 二维列表: (1, 2)
process_data([1, 2, 3]) # 列表,长度: 3
process_data({"key": "value"})

5.3 实践建议

  1. 优先使用 if-elif-else 的场景
    • 条件简单,分支不多
    • 条件表达式复杂,涉及多个变量的组合判断
    • 需要支持 Python 3.10 以下版本
    • 条件判断需要动态计算或频繁变更
  2. 优先使用 match-case 的场景
    • 处理结构化数据(如字典、元组、列表等)
    • 根据类型执行不同操作
    • 匹配多种可能的值或模式组合
    • 需要解构复杂数据结构并提取特定部分
    • 在 Python 3.10+ 环境中,追求代码可读性和简洁性
    • 处理枚举类型或状态机等需要明确匹配的场景
  3. 性能考量
    • 对于简单条件判断,两种方式性能差异不大
    • 在 Python 3.12+ 中,复杂的多分支模式匹配场景下,match-case 性能比 if-elif-else高20-30%
    • 当需要频繁匹配相同模式时,match-case 的预编译特性使其更高效
  4. 可维护性考量
    • match-case 通过明确的模式描述,使代码意图更清晰
    • 结构化的模式匹配减少了代码冗余,特别是在处理多种相似情况时
    • 编译器会检查模式的穷尽性,减少遗漏情况的风险

练习:


第一部分

  1. 计算并写出运行结果。if-elif-else 执行流程、循环基础逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 代码1:if-elif-else 执行顺序
score = 75
if score >= 90:
print("优秀")
elif score >= 80:
print("良好")
elif score >= 60:
print("及格")
else:
print("不及格")
# 输出:____

# 代码2:for 循环累加
total = 0
for i in range(1, 5):
total += i
print(total)
# 输出:____

# 代码3:break 与 continue
for i in range(1, 6):
if i == 3:
continue
if i == 5:
break
print(i, end=" ")
# 输出:____
  1. 补全代码
    (1)用 if-elif-else 实现成绩分级
1
2
3
4
5
6
7
8
9
score = int(input("请输入考试分数(0-100):"))
if ____:
print("优秀(90-100)")
elif ____:
print("良好(80-89)")
elif ____:
print("及格(60-79)")
else:
print("不及格(0-59)")

(2)用 while 循环计算 1 到 100 的和

1
2
3
4
5
6
total = 0
i = 1
while ____:
total += i
____ # 补全:让 i 自增 1
print(f"1到100的和是:{total}")

(3)用 match-case 判断简单的操作类型

1
2
3
4
5
6
7
8
9
10
11
12
op = input("请输入操作(add/sub/mul/div):")
match op:
case "add":
print("执行加法")
case ____:
print("执行减法")
case "mul":
print("执行乘法")
case "div":
print("执行除法")
case ____: # 补全:匹配所有其他情况
print("不支持的操作")
  1. 简单代码实现

(1)判断闰年:输入年份,用 if 判断是否为闰年(能被 4 整除但不能被 100 整除,或能被 400 整除)

1
2
year = int(input("请输入年份:"))
# 补全代码

(2)打印九九乘法表:用嵌套 for 循环打印 9x9 乘法表
(3)用 match-case 判断字符类型:输入一个字符,判断是数字、字母还是其他

1
2
char = input("请输入一个字符:")
# 补全代码
  1. 简单回答:
    1. breakcontinue 的区别是什么?分别举一个简单的使用场景。
    2. if-elif-else 和多个独立的 if 语句有什么区别?

第二部分

  1. 思考:match-case 的模式顺序

为什么下面的代码运行结果是 “普通数字”,而不是 “偶数” ?如何修改才能正确匹配?

1
2
3
4
5
6
num = 4
match num:
case _:
print("普通数字")
case 2 | 4 | 6:
print("偶数")

这说明了 match-case 模式匹配的什么规则?

  1. 代码实现:用 match-case 解构元组处理坐标

输入一个坐标元组 (x, y),用 match-case 实现:

  • 如果是 (0, 0):输出 原点
  • 如果是 (x, 0):输出 在 x 轴上,x 值为…
  • 如果是 (0, y):输出 在 y 轴上,y 值为…
  • 其他情况:输出 坐标为 (x, y)
1
2
coord = (0, 5)  # 可替换为其他坐标测试
# 补全代码
  1. 思考:循环中修改列表的坑
    下面的代码想删除列表中的所有偶数,但运行结果不对,为什么?如何修改才能正确实现?
1
2
3
4
5
nums = [1, 2, 3, 4, 5, 6]
for num in nums:
if num % 2 == 0:
nums.remove(num)
print(nums) # 实际输出:[1, 3, 5]?不对,实际是 [1, 3, 5, 6]!

提示:可以从“遍历列表时修改列表长度会影响索引”的角度思考,给出至少两种正确的修改方案。

  1. 代码实现:猜数字游戏

while 循环、if 判断和 break 实现:

  • 程序随机生成一个 1-100 的整数(提示:用 random.randint(1, 100)
  • 用户输入猜测的数字,程序提示 “大了” “小了” 或 “猜对了”
  • 猜对后退出循环,统计猜测次数
1
2
3
4
import random
target = random.randint(1, 100)
count = 0
# 补全代码
  1. 思考:while 循环的安全退出

为什么说“尽量用明确的退出条件,避免依赖 break 退出所有循环”?举一个可能因为 break 遗漏导致死循环的例子。

  1. 代码实现:match-case 的守卫条件(Guard)

match-case 结合守卫条件(if 子句)实现成绩分级,要求:

  • 90-100:优秀
  • 80-89:良好
  • 60-79:及格
  • 0-59:不及格
  • 分数不在 0-100 范围内:提示“分数无效”
1
2
score = 85
# 补全代码

参考答案


第一部分

  1. 计算并写出运行结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 代码1:if-elif-else 执行顺序
score = 75
if score >= 90:
print("优秀")
elif score >= 80:
print("良好")
elif score >= 60:
print("及格")
else:
print("不及格")
# 输出:及格

# 代码2:for 循环累加
total = 0
for i in range(1, 5): # range(1,5) 是 1,2,3,4
total += i
print(total)
# 输出:10

# 代码3:break 与 continue
for i in range(1, 6):
if i == 3:
continue # 跳过i=3,不打印
if i == 5:
break # 遇到i=5,直接结束循环
print(i, end=" ")
# 输出:1 2
  1. 补全代码

(1)用 if-elif-else 实现成绩分级

1
2
3
4
5
6
7
8
9
score = int(input("请输入考试分数(0-100):"))
if score >= 90:
print("优秀(90-100)")
elif score >= 80:
print("良好(80-89)")
elif score >= 60:
print("及格(60-79)")
else:
print("不及格(0-59)")

(2)用 while 循环计算 1 到 100 的和

1
2
3
4
5
6
7
total = 0
i = 1
while i <= 100: # 循环条件:i不超过100
total += i
i += 1 # 让i自增1,避免死循环
print(f"1到100的和是:{total}")
# 输出:1到100的和是:5050

(3)用 match-case 判断简单的操作类型

1
2
3
4
5
6
7
8
9
10
11
12
op = input("请输入操作(add/sub/mul/div):")
match op:
case "add":
print("执行加法")
case "sub":
print("执行减法")
case "mul":
print("执行乘法")
case "div":
print("执行除法")
case _: # 通配符,匹配所有其他情况
print("不支持的操作")
  1. 简单代码实现

(1)判断闰年

1
2
3
4
5
year = int(input("请输入年份:"))
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
print(f"{year}是闰年")
else:
print(f"{year}不是闰年")

(2)打印九九乘法表

1
2
3
4
for i in range(1, 10):  # 外层循环:控制行数(1-9)
for j in range(1, i + 1): # 内层循环:控制每行的列数(1-i)
print(f"{j}×{i}={i*j}", end="\t")
print() # 每行结束后换行

(3)用 match-case 判断字符类型

1
2
3
4
5
6
7
8
char = input("请输入一个字符:")
match char:
case _ if char.isdigit(): # 守卫条件:判断是否为数字
print("这是一个数字")
case _ if char.isalpha(): # 守卫条件:判断是否为字母
print("这是一个字母")
case _:
print("这是其他字符")
  1. 简单回答
    1. breakcontinue 的区别
      • break跳出整个循环,循环直接结束,不再执行后续的迭代
      • continue跳过当前这一次循环,直接进入下一次迭代
      • 场景示例:
        • break:猜数字游戏中,猜对了就用 break 结束循环
        • continue:遍历列表时,遇到不需要处理的元素,用 continue 跳过
    2. if-elif-else 和多个独立 if 的区别
      • if-elif-else互斥执行,只要有一个条件满足,后面的所有条件都不会再判断
      • 多个独立 if每个都会独立判断,即使前面的 if 满足了,后面的 if 还是会继续执行

第二部分

  1. 思考:match-case 的模式顺序
    问题原因match-case按顺序匹配的,只要遇到第一个匹配的模式就会执行,后面的模式直接跳过。

这里把通配符 _ 放在了最前面,所以不管输入什么,都会先匹配到 _,导致后面的具体模式永远不会执行。

修改方案:把具体模式放在前面,通配符 _ 放在最后:

1
2
3
4
5
6
7
num = 4
match num:
case 2 | 4 | 6:
print("偶数")
case _:
print("普通数字")
# 输出:偶数

核心规则match-case 必须把更具体的模式放在前面,更通用的模式放在后面。

  1. 代码实现:用 match-case 解构元组处理坐标
1
2
3
4
5
6
7
8
9
10
11
coord = (0, 5)  # 可替换为 (0,0)、(3,0)、(2,3) 测试
match coord:
case (0, 0):
print("原点")
case (x, 0):
print(f"在x轴上,x值为{x}")
case (0, y):
print(f"在y轴上,y值为{y}")
case (x, y):
print(f"坐标为 ({x}, {y})")
# 输出:在y轴上,y值为5
  1. 思考:循环中修改列表的坑

问题原因:遍历列表时直接删除元素,会导致列表长度动态变化,索引会跳过后续的元素。

原代码中,删除 2 后,列表变成 [1,3,4,5,6],下一次迭代直接跳到索引 2(元素 4),跳过了 3,最后 6 也没被处理到。

正确修改方案(两种)

1
2
3
4
5
6
7
8
9
10
11
# 方案1:遍历列表的副本,修改原列表
nums = [1, 2, 3, 4, 5, 6]
for num in nums.copy(): # 遍历nums的副本,不影响原列表的遍历
if num % 2 == 0:
nums.remove(num)
print(nums) # 输出:[1, 3, 5]

# 方案2:用列表推导式(推荐,更简洁高效)
nums = [1, 2, 3, 4, 5, 6]
nums = [num for num in nums if num % 2 != 0]
print(nums) # 输出:[1, 3, 5]
  1. 代码实现:猜数字游戏
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import random
target = random.randint(1, 100)
count = 0

while True:
guess = int(input("请猜一个1-100的数字:"))
count += 1
if guess > target:
print("大了")
elif guess < target:
print("小了")
else:
print(f"猜对了!你一共猜了{count}次")
break # 猜对了,结束循环
  1. 思考:while 循环的安全退出

原因

  • 明确的退出条件(比如 while i <= 100)更易读,一眼就能看出循环什么时候结束
  • 过度依赖 break 容易因为逻辑疏漏、代码修改时漏写 break,导致死循环

死循环示例

1
2
3
4
5
# 错误示例:漏写了 i += 1,导致 i 永远是1,循环永远不会结束
i = 1
while i <= 10:
print(i)
# 这里漏写了 i += 1!
  1. 代码实现:match-case 的守卫条件
1
2
3
4
5
6
7
8
9
10
11
12
13
score = 85
match score:
case _ if not 0 <= score <= 100:
print("分数无效")
case _ if score >= 90:
print("优秀")
case _ if score >= 80:
print("良好")
case _ if score >= 60:
print("及格")
case _:
print("不及格")
# 输出:良好

注意:守卫条件的顺序也很重要,要把“无效分数”的判断放在最前面,避免无效分数进入后续的分级判断。