Python 结构化模式匹配完全指南(match-case)
Python 3.10 引入结构化模式匹配:match-case 语法处理字面量、序列、字典、类实例与守卫条件,替代冗长的 if-elif 链。本文系统讲解用法与最佳实践。
直接回答:结构化模式匹配(match-case)让"根据数据的形状分支处理"变得声明式:不仅匹配值,还能解构序列、字典、对象并顺带绑定变量——长的 if-elif 链从此有了优雅的替代。
基本语法
def http_status(code):
match code:
case 200:
return "成功"
case 404:
return "页面不存在"
case 500 | 502 | 503: # 多值或
return "服务器错误"
case _: # 通配兜底
return "未知状态"
| 表示"或"(注意不是 or),_ 是兜底通配——忘了兜底且没匹配上时,静默什么都不做(不报错),这是新手最常见的意外。
按类型匹配
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def area(shape):
match shape:
case int() | float() as n: # 匹配数值并绑定为 n
return n * n
case str():
return "字符串没有面积"
case Point(x=0, y=0): # 类实例 + 属性匹配
return 0
case Point(x=x, y=y): # 解构属性
return abs(x * y)
类型检查 + 属性解构一步到位,以前要 isinstance + 属性访问两道工序。
序列解构
for command in commands: # commands、move、pick 由命令处理模块提供
match command.split():
case ["quit"]:
break
case ["go", direction]:
move(direction)
case ["pick", *items]:
for item in items:
pick(item)
case ["drop", *rest] if len(rest) > 3:
print("一次最多丢 3 个")
*rest 收集剩余元素,if 守卫加任意条件——适合表达命令结构。序列模式不匹配任意迭代器,也不会把字符串本身拆成字符序列匹配。
字典匹配
match event:
case {"type": "click", "x": x, "y": y}:
handle_click(x, y)
case {"type": "key", "key": "Enter"}:
submit()
case {"type": str() as t}:
print(f"未处理的事件: {t}")
字典匹配是部分匹配:只要声明的键存在且值吻合即命中,多余键不影响——处理 JSON 事件的理想工具。
什么时候不用 match
- 简单两三分支:if-else 更直白;
- 需要复杂布尔逻辑:守卫能写但可读性差,不如 if;
- 按值查表:
dict.get()一行的事别动用 match。
match 的甜区是**"数据结构驱动"的分支**——事件、消息、AST、命令分发。
常见问题(FAQ)
Q:case 里的名字是赋值还是比较?
A:裸名字是绑定(赋值给新变量),不是比较!要比较常量必须带点号(Color.RED)或先用字面量。case RED: 里的 RED 会变成新变量——这是 match 最大的坑。
Q:match 和 if-elif 性能有差吗?
A:不存在普遍适用的性能优胜结论。先按可读性选择,热点再以真实输入基准比较。
Q:能匹配自定义类吗?
A:能,按属性匹配;类里定义 __match_args__ 还能支持位置式匹配(case Point(0, 0))。
官方参考
本文基于官方文档整理,未进行运行时或性能测试。示例中的业务函数、数据模型和部署地址需结合项目补全;局部片段不等同于完整生产应用。