Python 3.10 引入的 match 语句(结构化模式匹配,Structural Pattern Matching)是 Python 历史上最大的语法变化之一。
简单来说,你可以把它看作是其他语言中 switch-case 的超级增强版。但它不仅能匹配具体的值,还能匹配数据的结构(如列表、字典、对象),并能同时将数据拆包(解构)赋值给变量。
以下是详细的讲解和常见场景:
最简单的用法是匹配字面值(数字、字符串等)。这就像传统的 switch 语句。
status = 404
match status:
case 200:
print("请求成功")
case 400:
print("错误请求")
case 404:
print("页面未找到")
case _:
# 下划线 _ 表示 "其他所有情况",类似于 switch 中的 default
print("未知状态")这是 match 真正强大的地方。它可以根据数据的形状来匹配,并直接提取其中的值。
假设你有一个坐标点,它可能是 (x, y) 形式的元组。
point = (0, 10)
match point:
case (0, 0):
print("原点")
case (0, y):
# 匹配 x 为 0,并将第二个元素赋值给变量 y
print(f"在 Y 轴上,Y={y}")
case (x, 0):
# 匹配 y 为 0,并将第一个元素赋值给变量 x
print(f"在 X 轴上,X={x}")
case (x, y):
print(f"坐标点在 ({x}, {y})")
case _:
print("这不是一个二维坐标")注意:这里不需要像写正则那样麻烦,Python 会自动帮你把值“拆”出来赋给变量
x或y。
你可以匹配字典中是否存在特定的 Key,并提取 Value。注意:它会忽略字典中未写出的其他 Key(部分匹配)。
user = {"name": "Alice", "role": "admin", "id": 123}
match user:
case {"role": "admin"}:
# 只要字典里有 role: admin 这一项就匹配
print("这是一个管理员")
case {"role": "guest", "name": name}:
# 匹配 role 是 guest,并把 name 的值提取出来
print(f"访客姓名: {name}")
case _:
print("权限不足或未知用户")它可以配合 dataclass 或普通类使用,直接检查对象的属性。
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
pt = Point(1, 5)
match pt:
case Point(x=0, y=0):
print("对象在原点")
case Point(x=x, y=y):
# 匹配是 Point 类型,并提取属性
print(f"Point 对象: x={x}, y={y}")使用 | 表示“或”的关系。
cmd = "stop"
match cmd:
case "start" | "go" | "play":
print("开始运行")
case "stop" | "quit" | "exit":
print("停止运行")你可以在匹配模式后加上 if 语句,进行更细致的逻辑判断。
point = (5, 5)
match point:
case (x, y) if x == y:
print(f"在对角线上: {x}")
case (x, y):
print(f"普通坐标: {x}, {y}")类似于列表解包中的 *args。
command = ["move", "up", 10, 20]
match command:
case ["quit"]:
print("退出")
case ["move", direction, *steps]:
# direction 匹配 "up"
# steps 匹配剩余列表 [10, 20]
print(f"向 {direction} 移动,步骤: {steps}")- 可读性更强:处理复杂数据结构(特别是嵌套的 JSON 或配置字典)时,比一堆
if isinstance(...) and dict.get(...)清晰得多。 - 解构赋值:在匹配的同时直接拿到你想要的数据,少写很多赋值代码。
- 安全性:强制你考虑数据结构,如果结构不匹配,代码逻辑不会乱跑。
您可以试着把手中一个复杂的 if-elif 链(特别是涉及到解析数据结构的)改写成 match 语句,看看代码是否变得更清爽了。