match(3.10+)是结构模式匹配而非 switch:模式可以解构序列、映射与对象,并把子部件绑定为变量。
字面模式与捕获模式
def handle(cmd: str) -> str:
match cmd.split():
case ["quit"]:
return "退出"
case ["go", direction]: # "go" 是字面模式,direction 是捕获模式
return f"前往 {direction}"
case _:
return "未知命令"关键区别:小写裸名是捕获模式(总是匹配并绑定新变量),不是值比较。想匹配常量必须用限定名:
match color:
case RED: # ❌ 捕获:把 color 绑定为 RED,永远匹配成功
...
case Color.RED: # ✅ 带点号的属性访问才是字面比较
...序列与映射模式
match data:
case [x, y]: # 恰好两个元素,解包绑定
...
case [first, *rest]: # 星号解包,任意长度
...
case [_, _, _]: # 通配符占位:恰好三个元素、不关心内容
...
case {"type": "point", "x": x, "y": y}: # 含这些键即匹配,允许额外键
...序列模式匹配任何实现序列协议的对象(list/tuple 等,见 数据模型与内建序列);str 和 bytes 不算,避免误伤字符串分支。
类模式与 match_args
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
match p:
case Point(0, 0): # 位置模式:按 __match_args__ 顺序匹配字段
print("原点")
case Point(x, y) if x == y: # 守卫可引用已绑定的变量
print("对角线")
case Point(x=0, y=y): # 关键字模式:按字段名匹配
print(f"在 y 轴上, y={y}")数据类 dataclass 自动生成 __match_args__ = ("x", "y"),天然支持位置类模式;普通类需自行定义该类属性。
或模式与守卫
ALLOWED = {"run", "walk"}
match cmd:
case ["drop" | "discard", item]: # | 组合多个字面量
drop(item)
case [action] if action in ALLOWED: # 模式匹配成功后再判断守卫
run(action)
case _:
pass守卫失败时不算匹配,继续尝试下一个 case;模式先于守卫求值,守卫里可使用该模式绑定的变量。
常见误区
- 首个匹配的 case 即结束,不写
break;case 体也不能为空 _是通配符不绑定值,case _:必须放在最后- 匹配只看”形似”:序列模式允许通配、映射模式忽略多余键——需要严格结构校验就在守卫里补