Python(十四) 中的 match-case 模式匹配
一、什么是 match-case
match-case 是 Python 3.10 开始加入的一种语法,中文通常叫“模式匹配”。
它的作用是:根据一个值的不同情况,选择执行不同的代码。
从功能上看,match-case 和 if...elif...else 有些相似,都是用来做分支判断的。
但是 match-case 更适合处理下面这类情况:
一个变量可能有多种固定取值
一个数据结构可能有不同形状
需要根据列表、元组、字典等结构进行判断
代码中有很多 if...elif...elif...
生活化理解:
拿到一个东西,看看它符合哪种情况。
符合第一种,就按第一种处理。
符合第二种,就按第二种处理。
都不符合,就按默认方式处理。
例如:
command = "start"
match command:
case "start":
print("开始")
case "stop":
print("停止")
case "pause":
print("暂停")
case _:
print("未知命令")
这段代码的意思是:
如果 command 是 "start",输出“开始”。
如果 command 是 "stop",输出“停止”。
如果 command 是 "pause",输出“暂停”。
如果都不是,输出“未知命令”。
二、match-case 的基本格式
语法格式:
match 要匹配的对象:
case 模式1:
模式1匹配成功时执行的代码
case 模式2:
模式2匹配成功时执行的代码
case 模式3:
模式3匹配成功时执行的代码
case _:
前面都不匹配时执行的代码
说明:
match 后面写要判断的对象。
case 后面写匹配规则。
哪个 case 匹配成功,就执行哪个 case 下面的代码。
case _ 表示默认情况,类似 else。
注意:match 和 case 后面都要加冒号。
示例:根据星期几输出安排。
day = "周六"
match day:
case "周一":
print("上班")
case "周二":
print("上班")
case "周三":
print("上班")
case "周四":
print("上班")
case "周五":
print("上班")
case "周六":
print("休息")
case "周日":
print("休息")
case _:
print("输入错误")
三、match-case 和 if-elif-else 的关系
很多简单的 match-case 都可以用 if...elif...else 实现。
例如:
level = "A"
match level:
case "A":
print("优秀")
case "B":
print("良好")
case "C":
print("及格")
case _:
print("未知等级")
可以写成:
level = "A"
if level == "A":
print("优秀")
elif level == "B":
print("良好")
elif level == "C":
print("及格")
else:
print("未知等级")
二者的区别可以这样讲:
if...elif...else 更通用,适合各种条件判断。
match-case 更适合“把一个对象拿来匹配多种情况”。
如果只是判断大小关系,比如:
score = 85
if score >= 90:
print("优秀")
elif score >= 60:
print("及格")
else:
print("不及格")
这种场景使用 if...elif...else 更自然。
如果是判断固定命令、固定状态、固定结构,使用 match-case 会更清楚。
四、字面量模式
字面量模式就是直接匹配具体的值。
常见字面量包括:
数字
字符串
布尔值
None
示例:
status = 404
match status:
case 200:
print("请求成功")
case 404:
print("页面不存在")
case 500:
print("服务器错误")
case _:
print("未知状态码")
输出结果:
页面不存在
再看一个字符串示例:
role = "admin"
match role:
case "admin":
print("管理员")
case "teacher":
print("教师")
case "student":
print("学生")
case _:
print("普通用户")
五、通配符模式 _
_ 是通配符模式,表示“其他所有情况”。
它类似于 if...elif...else 中的 else。
示例:
command = "delete"
match command:
case "add":
print("添加数据")
case "update":
print("修改数据")
case "search":
print("查询数据")
case _:
print("无法识别的命令")
这里的 case _: 表示:
如果前面的 case 都没有匹配成功,就执行这里。
教学提醒:
通常建议把 case _ 放在最后。
因为它可以匹配所有情况,如果放在前面,后面的 case 就没有机会执行了。
六、或模式 |
| 表示“或者”,可以让多个值共用同一段代码。
示例:判断是否是周末。
day = "周日"
match day:
case "周六" | "周日":
print("周末")
case "周一" | "周二" | "周三" | "周四" | "周五":
print("工作日")
case _:
print("输入错误")
这里:
case "周六" | "周日":
表示:
如果 day 是 "周六" 或者 "周日",就匹配成功。
这个写法比写多个重复的 case 更简洁。
七、变量捕获模式
在 case 中,如果直接写一个变量名,它不是在比较变量值,而是在“捕获”匹配到的内容。
这个地方是初学者非常容易出错的。
示例:
value = 10
match value:
case x:
print("匹配到的值是:", x)
输出结果:
匹配到的值是: 10
这里的 case x: 会匹配任何值,并把这个值保存到变量 x 中。
也就是说:
case x 不是判断 value 是否等于 x。
case x 是把 value 的值赋给 x。
如果想匹配具体的字符串或数字,要直接写字面量:
match value:
case 10:
print("值是 10")
教学提醒:
case 后面直接写普通变量名,会匹配所有内容。
所以不要把它误认为是相等判断。
八、带条件的匹配 guard
case 后面可以加 if 条件,这叫守卫条件,也常叫 guard。
它的作用是:先匹配模式,再判断额外条件。
示例:判断数字正负。
num = 8
match num:
case x if x > 0:
print("正数")
case x if x < 0:
print("负数")
case 0:
print("零")
解释:
case x 会先捕获 num 的值。
if x > 0 再判断这个值是否大于 0。
再看一个成绩示例:
score = 85
match score:
case x if x >= 90:
print("优秀")
case x if x >= 60:
print("及格")
case x if x >= 0:
print("不及格")
case _:
print("成绩不合法")
不过要提醒学生:如果主要是比较大小,用 if...elif...else 通常更直观。
九、序列模式
序列模式可以匹配列表、元组等序列结构。
也就是说,match-case 不只能看“值是多少”,还可以看“结构长什么样”。
示例:匹配坐标。
point = (3, 5)
match point:
case (0, 0):
print("原点")
case (0, y):
print("在 y 轴上,y =", y)
case (x, 0):
print("在 x 轴上,x =", x)
case (x, y):
print("普通点,x =", x, "y =", y)
输出结果:
普通点,x = 3 y = 5
解释:
case (0, 0) 匹配坐标是原点。
case (0, y) 匹配第一个值是 0 的坐标,并捕获第二个值。
case (x, 0) 匹配第二个值是 0 的坐标,并捕获第一个值。
case (x, y) 匹配两个元素的坐标,并捕获两个值。
星号 * 的使用
序列模式中可以使用 * 捕获多个元素。
示例:
data = [1, 2, 3, 4]
match data:
case [first, *middle, last]:
print("第一个:", first)
print("中间:", middle)
print("最后一个:", last)
输出结果:
第一个: 1
中间: [2, 3]
最后一个: 4
这里:
first 捕获第一个元素
middle 捕获中间多个元素
last 捕获最后一个元素
十、字典模式
字典模式可以根据字典中的键和值进行匹配。
示例:处理用户信息。
user = {"name": "小明", "role": "student"}
match user:
case {"role": "admin"}:
print("管理员用户")
case {"role": "teacher"}:
print("教师用户")
case {"role": "student", "name": name}:
print("学生:", name)
case _:
print("未知用户")
输出结果:
学生: 小明
解释:
case {"role": "student", "name": name}
表示匹配 role 是 "student",并把 name 对应的值保存到变量 name 中。
注意:
字典模式通常只要求匹配指定的键。
字典里有其他键,一般不影响匹配。
示例:
user = {"name": "小红", "role": "student", "age": 18}
match user:
case {"role": "student"}:
print("这是学生")
虽然字典中还有 name 和 age,但因为 role 匹配成功,所以会输出:
这是学生
十一、类模式
match-case 也可以匹配对象。
初学阶段可以简单了解,不必讲得太深。
示例:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
person = Student("小明", 18)
match person:
case Student(name=name, age=age):
print("学生姓名:", name)
print("学生年龄:", age)
case _:
print("不是学生对象")
输出结果:
学生姓名: 小明
学生年龄: 18
解释:
case Student(name=name, age=age)
表示匹配 Student 类型的对象,并取出它的 name 和 age 属性。
如果当前课程还没有讲类,可以先跳过这一节。
十二、匹配顺序很重要
match-case 会从上往下依次匹配。
一旦某个 case 匹配成功,后面的 case 就不会再判断。
示例:
command = "start"
match command:
case _:
print("默认处理")
case "start":
print("开始")
这段代码有问题,因为 case _: 可以匹配所有情况。
所以会输出:
默认处理
后面的 case "start": 永远不会执行。
正确写法:
command = "start"
match command:
case "start":
print("开始")
case _:
print("默认处理")
教学提醒:
更具体的 case 写在前面。
默认情况 case _ 写在最后。
十三、常见注意事项
1. Python 版本必须是 3.10 或更高
match-case 是 Python 3.10 才加入的语法。
如果使用 Python 3.9 或更早版本,会报语法错误。
可以用下面的代码查看 Python 版本:
import sys
print(sys.version)
2. match 和 case 后面都要加冒号
错误写法:
match command
case "start"
print("开始")
正确写法:
match command:
case "start":
print("开始")
3. case 下方代码要正确缩进
正确写法:
match command:
case "start":
print("开始")
错误写法:
match command:
case "start":
print("开始")
Python 使用缩进表示代码块,通常使用 4 个空格作为一级缩进。
4. case _ 通常放在最后
case _: 表示默认匹配,可以匹配所有没有被前面处理的情况。
如果放在前面,后面的 case 通常就没有意义了。
推荐写法:
match value:
case 1:
print("一")
case 2:
print("二")
case _:
print("其他")
5. case x 不是判断是否等于变量 x
这是 match-case 中非常重要的易错点。
示例:
x = 10
value = 20
match value:
case x:
print("匹配成功,x =", x)
输出结果:
匹配成功,x = 20
原因:
case x 会捕获 value 的值,并把它赋给 x。
它不是判断 value 是否等于原来的 x。
如果要判断固定值,直接写固定值:
match value:
case 10:
print("值是 10")
如果要用条件判断变量之间是否相等,可以使用 guard:
x = 10
value = 20
match value:
case y if y == x:
print("value 等于 x")
case _:
print("value 不等于 x")
6. 不要把 match-case 当成所有 if 的替代品
match-case 很有用,但不是所有情况都适合用它。
适合使用 if...elif...else 的情况:
判断大小关系
判断多个复杂条件
条件之间不是围绕同一个对象展开
适合使用 match-case 的情况:
根据一个对象的不同取值进行处理
根据列表、元组、字典等结构进行处理
命令分发、状态判断、数据解析
7. 注意不要写过于复杂的模式
match-case 可以写得很强大,但如果模式太复杂,学生会看不懂。
教学阶段建议先掌握:
字面量模式
通配符 _
或模式 |
guard 条件
序列模式
字典模式
类模式可以作为拓展内容。
十四、课堂示例
示例 1:命令菜单
command = input("请输入命令 add/delete/search:")
match command:
case "add":
print("执行添加功能")
case "delete":
print("执行删除功能")
case "search":
print("执行查询功能")
case _:
print("未知命令")
讲解重点:
match command 表示要匹配 command 的值。
不同的 case 对应不同命令。
case _ 处理未知命令。
示例 2:HTTP 状态码
status = 200
match status:
case 200:
print("成功")
case 400:
print("请求错误")
case 404:
print("资源不存在")
case 500:
print("服务器错误")
case _:
print("未知状态")
这个例子适合讲解字面量模式。
示例 3:根据坐标判断位置
point = (0, 5)
match point:
case (0, 0):
print("原点")
case (0, y):
print("在 y 轴上,y =", y)
case (x, 0):
print("在 x 轴上,x =", x)
case (x, y):
print("普通点,x =", x, "y =", y)
这个例子适合讲解序列模式和变量捕获。
示例 4:处理字典数据
message = {"type": "text", "content": "你好"}
match message:
case {"type": "text", "content": content}:
print("文本消息:", content)
case {"type": "image", "url": url}:
print("图片地址:", url)
case {"type": "video", "url": url}:
print("视频地址:", url)
case _:
print("未知消息类型")
这个例子适合讲解字典模式,也比较接近真实开发中的数据处理。
十五、课堂练习
练习 1:判断季节
要求:输入季节名称,输出对应提示。
参考代码:
season = input("请输入季节:")
match season:
case "春天":
print("万物复苏")
case "夏天":
print("天气炎热")
case "秋天":
print("秋高气爽")
case "冬天":
print("天气寒冷")
case _:
print("输入错误")
练习 2:简单计算器
要求:根据运算符执行加减乘除。
参考代码:
a = 10
b = 5
op = "+"
match op:
case "+":
print(a + b)
case "-":
print(a - b)
case "*":
print(a * b)
case "/":
print(a / b)
case _:
print("不支持的运算符")
练习 3:判断坐标位置
要求:根据坐标判断在原点、x 轴、y 轴还是普通位置。
参考代码:
point = (3, 0)
match point:
case (0, 0):
print("原点")
case (x, 0):
print("在 x 轴上")
case (0, y):
print("在 y 轴上")
case (x, y):
print("普通点")
练习 4:处理用户角色
要求:根据用户字典中的角色输出不同信息。
参考代码:
user = {"name": "小明", "role": "teacher"}
match user:
case {"role": "admin", "name": name}:
print(name, "是管理员")
case {"role": "teacher", "name": name}:
print(name, "是教师")
case {"role": "student", "name": name}:
print(name, "是学生")
case _:
print("未知用户")
十六、教学建议
讲解 match-case 时,可以按照下面顺序:
1. 先复习 if...elif...else
2. 说明 match-case 也是做多分支判断
3. 用命令菜单或状态码引入基本语法
4. 讲 case _ 相当于默认情况
5. 讲 | 可以合并多个匹配值
6. 再讲序列模式和字典模式
7. 最后强调变量捕获这个易错点
可以用下面的问题引导学生:
如果一个命令有很多种取值,用很多 elif 会不会太长?
如果一个坐标是 (0, 5),能不能直接判断它在 y 轴上?
如果一个字典表示消息,能不能根据 type 字段选择不同处理方式?
case x 到底是判断 x,还是把值赋给 x?
教学重点建议放在:
基本语法
case _
或模式 |
变量捕获
序列模式
字典模式
匹配顺序
十七、总结
match-case 是 Python 中用于模式匹配的语法。
它可以根据一个对象的不同值或不同结构,选择执行不同代码。
可以这样记:
match:拿出一个对象来匹配
case:列出一种可能的情况
case _:其他所有情况
|:表示或者
case x:捕获值,不是比较变量
match-case 适合:
命令分发
状态判断
处理列表、元组、字典等结构化数据
替代过长的 if...elif...elif...
需要注意:
1. Python 版本必须是 3.10 或更高
2. match 和 case 后面都要加冒号
3. case _ 通常放在最后
4. 匹配顺序从上到下
5. case x 是变量捕获,不是相等判断
6. 不要把 match-case 当成所有 if 的替代品
一句话总结:
match-case 让程序可以根据“值是什么”或“结构长什么样”来选择不同处理方式,特别适合处理多种固定情况和结构化数据。