Python 语法精炼14
match / case 语句
该用法在 Python3.10+ 加入
1 | match <subject>: |
match:开始匹配语句。<subject>:要进行匹配的值(类似 switch 的“输入值”)。case:每个分支的匹配模式。_:通配符,表示 “任意匹配”(类似default)。- 匹配成功后只执行第一个符合的
case,不会自动贯穿(即不需要break)。
基本概念
传统 if-elif 判断是布尔逻辑,而 match/case 是 结构解构 + 匹配。
例如:
1 | match x: |
看似是 switch,但实际上 case 模式能“解构”更复杂的数据结构,如:
- 序列 / 元组 / 字典
- 带属性类实例
- 带类型约束
- 具名元组 / dataclass / 自定义类
匹配类型与模式种类
Python 模式匹配支持多种模式类型:
| 模式类型 | 示例 | 说明 |
|---|---|---|
| 常量模式 | case 1: |
与具体值匹配 |
| 通配符模式 | case _: |
匹配任意值 |
| 捕获模式 | case x: |
匹配任意值并绑定到变量 x |
| 序列模式 | case [a, b]: |
匹配长度相同的序列并解构 |
| 映射模式 | case {"x": x, "y": y}: |
匹配字典并提取键值 |
| 类模式 | case Point(x, y): |
匹配类实例并解构字段 |
| 守卫模式(条件匹配) | case pattern if condition: |
匹配后再判断附加条件 |
| OR 模式(联合匹配) | case 0 | 1 | 2: |
任意一个匹配即成功 |
详细讲解每种模式
常量模式
1 | match command: |
简单、清晰,相当于 switch-case。
捕获模式
1 | match data: |
这会匹配任意值并绑定到 x。
注意:如果想匹配变量名本身的值,而不是绑定新变量,必须使用 value 前加点号:
1 | value = 42 |
序列模式
可以匹配解构序列的结构:
1 | match [1, 2, 3]: |
*rest 表示剩余元素(类似可变参数)。
还可以嵌套:
1 | match [1, [2, 3]]: |
映射模式
用于匹配字典结构:
1 | match {"x": 1, "y": 2, "z": 3}: |
还可以使用 **rest 捕获剩余键:
1 | match data: |
类模式
可以匹配对象的类型和属性:
1 | class Point: |
可以使用带类型的匹配:
1 | match value: |
守卫模式(条件匹配)
在模式后加上 if 条件,进一步限制:
1 | match x: |
OR 模式(联合匹配)
可以在一个 case 中匹配多个模式:
1 | match command: |
应用示例
综合示例:抽象语法树匹配
模式匹配非常适合解析树形结构(如语法树):
1 | def eval_expr(expr): |
进阶示例:定义可匹配类
通过 __match_args__ 控制匹配字段顺序:
1 | class Point: |
这会按照 __match_args__ 解构。
match/case vs if/elif
| 特性 | match/case | if/elif |
|---|---|---|
| 简单相等判断 | ✅ 可行 | ✅ 可行 |
| 多模式匹配 | ✅ 方便 | ❌ 繁琐 |
| 解构数据结构 | ✅ 直接支持 | ❌ 需要手动索引 |
| 条件守卫 | ✅ 支持 | ✅ 支持 |
| 类型安全性 | ✅ 更清晰 | ❌ 依赖手动判断 |
| 性能 | ⚖️ 差别不大 | ⚖️ 差别不大 |
使用场景
✅ 适合用的情况:
- 数据解析(JSON / dict / AST)
- 命令路由(类似 switch)
- 协议包解构
- 事件处理分发
- 状态机逻辑分支
❌ 不适合的情况:
- 仅有简单 if 判断;
- 需要动态逻辑的复杂条件。
注意事项
case _:必须放在最后,否则会遮蔽后续分支;- 捕获变量名会自动绑定新的局部变量;
- 匹配是结构性的,而不是类型强制的,如
[1, 2]匹配 tuple 也行; - 对类匹配时,类需要支持
__match_args__或具名参数; - 模式匹配不支持
case穿透(没有“fallthrough”)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Telason!
