脚本专家 发表于 2026-7-13 09:00:01

Python 3.10结构化模式匹配match-case基础与实战

2021年10月发布的Python 3.10带来了结构化模式匹配(Structural Pattern Matching),即match-case语句。它的能力远超传统switch,不仅能做值匹配,还能解构序列、映射和类实例,并支持守卫条件与变量绑定。本教程从基础语法到实战案例,系统讲解match-case的使用方法。

所有代码示例需在Python 3.10及以上版本运行,可用以下代码检查环境兼容性:


import sys
if sys.version_info >= (3, 10):
    print("✅ 支持 match-case")
else:
    print("❌ 请升级到 Python 3.10 或更高版本")


一、基础语法

1. 最简单的模式匹配

match语句后接待匹配值,每个case跟一个模式和一个冒号,形如:


def what_day(day):
    match day:
      case 1:
            return "星期一"
      case 2:
            return "星期二"
      case 7:
            return "星期日"
      case _:
            return "无效的日期数字"


下划线_是通配符,匹配任何未在上方明确匹配的值。注意_不会绑定值,而普通变量名会绑定。

2. OR模式匹配多个值

用竖线|分隔多个值,实现“或”逻辑:


def classify_number(n):
    match n:
      case 0:
            return "零"
      case 1 | 2 | 3:
            return "小数字(1-3)"
      case 4 | 5 | 6:
            return "中数字(4-6)"
      case 7 | 8 | 9:
            return "大数字(7-9)"
      case _:
            return "超出范围"


3. 变量绑定

这是match-case超越switch的关键:在匹配序列或结构时,模式中的变量会自动捕获对应的元素。


def process_command(command):
    match command.split():
      case ["quit"]:
            print("退出程序")
      case ["add", x]:
            print(f"加上 {x}")
      case ["add", x, y]:
            print(f"{x} + {y} = {int(x) + int(y)}")
      case _:
            print("未知命令")


二、结构化模式匹配(核心特性)

1. 匹配序列(列表/元组)

支持按长度、位置以及使用星号收集剩余元素:


def analyze_sequence(seq):
    match seq:
      case []:
            return "空序列"
      case :
            return f"单元素: {x}"
      case :
            return f"两元素: {x}, {y}"
      case :
            return f"首元素: {first}, 剩余: {rest}"


星号也可出现在中间,例如会分离首、尾及中间剩余元素。

2. 匹配映射(字典)

按字典键进行模式匹配,变量绑定对应值。注意case顺序影响匹配结果:更具体的模式应写在前面。


def analyze_config_fixed(config):
    match config:
      case {"host": host, "port": port, "debug": bool(debug)}:
            return f"服务器: {host}:{port}, 调试={'开' if debug else '关'}"
      case {"host": host, "port": int(port)}:
            return f"服务器: {host}:{port}"
      case _:
            return "无效配置"


这里利用内置类型名(如bool, int)进行类型守卫。在模式中直接写int(port)会将port与int类型匹配,同时转换类型。

3. 匹配类实例

模式中可以调用构造函数并进行属性解构:


class Point:
    def __init__(self, x, y):
      self.x = x
      self.y = y

def describe_shape(shape):
    match shape:
      case Point(x=0, y=0):
            return "原点"
      case Point(x=x, y=y):
            return f"点({x}, {y})"
      case _:
            return "未知形状"


三、守卫条件(Guard)

在模式后添加if条件,做额外逻辑判断:


def classify_value(x):
    match x:
      case int(n) if n > 0:
            return f"正整数: {n}"
      case int(n) if n < 0:
            return f"负整数: {n}"
      case int(n):
            return "零"
      case str(s) if len(s) > 10:
            return f"长字符串({len(s)}字符): {s[:10]}..."
      case str(s):
            return f"短字符串: {s}"
      case _:
            return "其他类型"


守卫条件可结合OR模式,但注意优先级:case模式 if条件中的|需要括号(如case int(n) if n < 0 | n > 150: 实际应写作 case int(n) if n < 0 or n > 150:,注意原文的|用法有误,正确写法是条件表达式内用or)。

四、match-case vs if-elif-else

match-case适合值匹配和结构解构;if-elif-else适合范围比较、复杂逻辑。两者可混合使用,例如先用match按类型分支,再在case内部用if细分:


def smart_classifier(obj):
    match obj:
      case int(n):
            if n < 0:
                return "负整数"
            elif n == 0:
                return "零"
            else:
                return "正整数"
      case str(s):
            if len(s) == 0:
                return "空字符串"
            else:
                return "非空字符串"
      case _:
            return "其他类型"


五、实战案例

1. JSON数据验证与解析

利用模式匹配快速验证并提取字段:


def parse_user_data(data):
    match data:
      case {
            "name": str(name),
            "age": int(age),
            "email": str(email),
            **extra
      } if 0 < age < 150 and "@" in email:
            return {"name": name, "age": age, "email": email, "valid": True}
      case {"name": str(name), "age": int(age)} if 0 < age < 150:
            return {"name": name, "age": age, "valid": True, "warnings": ["缺少邮箱"]}
      case dict():
            return {"valid": False, "errors": ["数据格式不正确"]}
      case _:
            return {"valid": False, "errors": ["输入不是字典"]}


2. 简易计算器

用match-case处理命令解析和操作符分发:


def calculator():
    print("简易计算器(输入 quit 退出)")
    while True:
      user_input = input("> ").strip()
      if not user_input:
            continue
      match user_input.split():
            case ["quit" | "exit" | "q"]:
                print("再见!")
                break
            case :
                try:
                  a, b = float(left), float(right)
                  match op:
                        case "+":
                            result = a + b
                        case "-":
                            result = a - b
                        case "*" | "×":
                            result = a * b
                        case "/" | "÷":
                            if b == 0:
                              print("除数不能为零")
                              continue
                            result = a / b
                        case "**" | "^":
                            result = a ** b
                        case "%":
                            result = a % b
                        case _:
                            print("未知操作符")
                            continue
                  print(f"{a} {op} {b} = {result}")
                except ValueError:
                  print("请输入有效数字")
            case _:
                print("格式错误,请使用: <数字> <操作符> <数字>")


3. 抽象语法树处理器

利用match-case递归求值表达式树:


class Number:
    def __init__(self, value):
      self.value = value
class BinOp:
    def __init__(self, left, op, right):
      self.left = left
      self.op = op
      self.right = right
class UnaryOp:
    def __init__(self, op, operand):
      self.op = op
      self.operand = operand

def evaluate(expr):
    match expr:
      case Number(value=n):
            return n
      case BinOp(left=l, op="+", right=r):
            return evaluate(l) + evaluate(r)
      case BinOp(left=l, op="*", right=r):
            return evaluate(l) * evaluate(r)
      case UnaryOp(op="-", operand=opd):
            return -evaluate(opd)
      case _:
            raise ValueError("未知表达式")


构建表达式(-5 + 3) * 2:


expr = BinOp(BinOp(UnaryOp("-", Number(5)), "+", Number(3)), "*", Number(2))
print(evaluate(expr))# -4


总结:match-case是Python 3.10的重大特性,其结构化模式匹配能力让代码更清晰、更易维护。掌握它,你就能用更声明式的方式处理分支逻辑。建议在需要解构复杂数据结构或多值分支时优先使用,并与if-elif-else合理搭配。

热心网友6 发表于 2026-7-13 09:10:00

Re: Python 3.10结构化模式匹配match-case基础与实战

感谢楼主分享,非常系统!match-case 的序列解构和守卫条件真的比传统 switch 好用太多,尤其是 `` 和 `case int(n) if n > 0` 这种写法,简洁又直观。还没在项目里用上 3.10 的新特性,看完教程打算升级试试了。顺便问一下,最后那个带守卫条件的 `classify_value` 例子好像没贴完整?

热心网友6 发表于 2026-7-13 09:10:00

Re: Python 3.10结构化模式匹配match-case基础与实战

感谢楼主的详细教程!match-case确实比传统switch强大很多,尤其是解构序列和类实例的部分,让代码更简洁。有个问题想请教:在处理复杂嵌套数据结构时,match-case的性能如何?跟if-else链相比有没有明显差异?另外,通配符`_`和变量绑定在模式中的具体行为能再详细说一下吗?比如`_`与普通变量名在绑定上的区别。再次感谢!

热心网友6 发表于 2026-7-13 09:10:00

Re: Python 3.10结构化模式匹配match-case基础与实战

感谢楼主的详细教程,讲得非常系统!结构化模式匹配出来之后确实让很多场景的代码简洁了很多。不过最后那个守卫条件的示例好像没写完,第三个case之后是不是还有内容?另外想请教一下,匹配字典时如果键存在但值类型不对,比如 `{'host': 'localhost', 'port': '8080'}`,用了 `int(port)` 会匹配失败,但如果不写 `int()`,直接写 `port` 变量就会绑定字符串,对吗?期待楼主补充更多实战场景。
页: [1]
查看完整版本: Python 3.10结构化模式匹配match-case基础与实战