Python 3.10 更新了模式匹配,也就是 match-case。这并不是简简单单的对 C 语言 switch-case 的模仿,事实上 switch-case 是完全可以由 if-elif-elif… 代替的,而 match-case 最大的提升就是支持了解构——一种高级拆包形式,同时,这也是解构第一次在 Python 世界中出现。

解构与卫语句

模式匹配还支持卫语句,也就是在模式语句之后的 if 语句,模式匹配要同时满足模式语句以及卫语句(可选)才能成功匹配,不然就会转到下一个 case。

通配符与类型检查

_ 在模式匹配上下文中有特殊含义,它可以匹配任何模式,也就是说,你可以使用 case _ 来作为 if 语句的 else 使用。除此之外,模式匹配上下文中 str()float() 等并不是构造函数,而是作为类型检查,也就是说 case [str(text)] 表示匹配只含 1 项的序列(这也叫做序列匹配),且那一项必须为 str。

序列匹配的限制

必须说明的是,序列匹配只能匹配序列(str,bytes 以及迭代器都不支持解构,其中 str 和 bytes 是因为它们属于“原子”值,也就是一个整体),像列表、元组、range 以及数组等都是可以正常解构的。

基本语法示例

1
2
3
4
5
6
7
8
9
metro_areas = [
('Tokyo', 'JP', 36.933, (11.11, 55.55)),
('Shanghai', 'CN', 24.9, (31.1, 121.3))
]

for record in metro_areas:
match record:
case [str(name), _, _, (float(lat), float(lon))] if lon <= 0:
print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')

当然,匹配中也可以将 str(name) 改为确定的字符串如 'Shanghai',这样就只会匹配 'Shanghai' 一个了。

评价

模式匹配在某些情况下其实挺好用的,if 语句是比不了的,事实上它对 if 语句还能进一步简化。