模式匹配机制在 Python 3.10 中引入,称为 结构化模式匹配 ,并通过 match-case 语法实现。这个工具可以优雅简洁地分析复杂的数据结构,匹配模式。
在许多函数式编程语言(例如 Haskell、Scala)中,模式匹配已经被视为根据数据结构进行逻辑分支的方便方式。Python 一直没有这样的机制,而是使用 if-elif-else 链或解包。
复杂的嵌套数据结构(字典、列表、对象)通常需要多重类型、值和结构检查,这导致代码混乱且条件众多。
match-case 提供了一种声明式且可读的方式来描述数据处理的不同场景,考虑类型和结构而不堆砌条件。
def process(event): match event: case {"type": "click", "x": x, "y": y}: return f"Click at ({x}, {y})" case [command, *args]: return f"Command: {command}, args: {args}" case _: return "Unknown event" print(process({"type": "click", "x": 2, "y": 5})) # Click at (2, 5) print(process(["RUN", 1, 2, 3])) # Command: RUN, args: [1, 2, 3]
match-case 只按值匹配吗? 不是。匹配可以基于结构、类型、集合解包,甚至对象属性(如果指定了特殊方法 match_args)。
case 的顺序会影响 match 吗? 会。匹配是从上到下进行的,第一个符合的模板会被触发。后续的 case 不会被检查。
可以匹配自定义类吗? 可以,如果类实现了方法 match_args 和/或 getitem。那么模式匹配可以提取字段值。
class Point: __match_args__ = ("x", "y") def __init__(self, x, y): self.x = x self.y = y def where(obj): match obj: case Point(x, y): return f"Point at {x}, {y}" case _: return "Unknown" print(where(Point(1, 2))) # Point at 1, 2
优点:
负面案例: 开发者甚至对简单的布尔分支使用 match-case,导致代码变得复杂。优点:学习了新特性。缺点:失去了可读性,增加了错误的数量。
积极案例: 在一个有大量事件和嵌套结构的应用程序中(例如,图解析器),match-case 避免了繁琐的 if-elif,并集中化了解析。优点:可读性提高,错误数量减少。缺点:需要培训团队使用新语法。