Python基础指南之match-case模式匹配语句的使用教学

 更新时间:2026年07月13日 08:39:52   作者:星河耀银海  
Python 3.10引入了结构化模式匹配(match-case)语句,这是一个比传统switch更强大的特性,文章详细介绍了match-case的基础用法,这个新特性使Python能够更优雅地处理复杂的数据结构匹配场景,大大提升了代码的可读性和表达能力

一、开篇:Python 3.10的里程碑特性

2021年10月,Python 3.10正式发布,其中最引人注目的新特性就是结构化模式匹配(Structural Pattern Matching)——也就是match-case语句。这不仅仅是"Python版的switch",而是一个远比switch强大得多的特性。

先看看它长什么样:

# 经典的使用场景:根据状态码返回消息
def http_status_message(code):
    match code:
        case 200:
            return "OK"
        case 404:
            return "Not Found"
        case 500:
            return "Internal Server Error"
        case _:
            return "Unknown"

这看起来确实像其他语言的switch-case。但match-case的能力远超switch——它能匹配数据结构、解构对象、使用守卫条件,甚至能匹配自定义类的实例。

本文将从基础到高级,全面讲解这个Python的新利器。

版本要求

# match-case 需要 Python 3.10+
import sys
print(f"Python版本: {sys.version}")

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

二、match-case 基础语法

2.1 最简单的模式匹配

# 基本语法
# match subject:
#     case pattern1:
#         action1()
#     case pattern2:
#         action2()
#     case _:
#         default_action()

# 示例:星期几
def what_day(day):
    match day:
        case 1:
            return "星期一"
        case 2:
            return "星期二"
        case 3:
            return "星期三"
        case 4:
            return "星期四"
        case 5:
            return "星期五"
        case 6:
            return "星期六"
        case 7:
            return "星期日"
        case _:          # _ 是通配符,匹配任何值
            return "无效的日期数字"

print(what_day(1))    # 星期一
print(what_day(7))    # 星期日
print(what_day(0))    # 无效的日期数字

# 关于 _ 通配符
# _ 是一个特殊的"吸尘器"模式,匹配一切
# 不同于变量名(变量名会绑定值),_ 不会绑定

2.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 "超出范围"

for i in range(11):
    print(f"{i}: {classify_number(i)}")

# 可用于合并相似的处理逻辑
def is_weekend(day):
    match day.lower():
        case "saturday" | "sunday":
            return True
        case "monday" | "tuesday" | "wednesday" | "thursday" | "friday":
            return False
        case _:
            return None

2.3 匹配时的变量绑定

这是match-case超越switch的关键特性之一:

# match-case可以在匹配时提取值
def process_command(command):
    match command.split():
        case ["quit"]:
            print("退出程序")
        case ["hello"]:
            print("你好!")
        case ["add", x]:           # x 绑定到第二个元素
            print(f"加上 {x}")
        case ["add", x, y]:        # x, y 分别绑定
            print(f"{x} + {y} = {int(x) + int(y)}")
        case _:
            print("未知命令")

process_command("quit")          # 退出程序
process_command("add 10")        # 加上 10
process_command("add 10 20")     # 10 + 20 = 30
process_command("unknown xyz")   # 未知命令

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

3.1 匹配序列(列表/元组)

# 匹配不同长度和内容的序列
def analyze_sequence(seq):
    match seq:
        case []:
            return "空序列"
        case [x]:
            return f"单元素序列: {x}"
        case [x, y]:
            return f"两元素序列: {x}, {y}"
        case [x, y, z]:
            return f"三元素序列: {x}, {y}, {z}"
        case [first, *rest]:      # *rest 收集剩余元素
            return f"首元素: {first}, 剩余: {rest}"
        case _:
            return "不是序列"

print(analyze_sequence([]))               # 空序列
print(analyze_sequence([42]))             # 单元素序列: 42
print(analyze_sequence([1, 2]))           # 两元素序列: 1, 2
print(analyze_sequence([1, 2, 3, 4, 5])) # 首元素: 1, 剩余: [2, 3, 4, 5]

# * 也可以出现在中间
def extract_parts(seq):
    match seq:
        case [first, *middle, last]:
            return f"首={first}, 中={middle}, 尾={last}"
        case _:
            return "太短了"

print(extract_parts([1, 2, 3, 4, 5]))  # 首=1, 中=[2, 3, 4], 尾=5
print(extract_parts([1, 2]))           # 首=1, 中=[], 尾=2
print(extract_parts([1]))              # 太短了

3.2 匹配映射(字典)

# 匹配字典结构
def analyze_config(config):
    match config:
        case {"host": host, "port": port}:
            return f"服务器: {host}:{port}"
        case {"host": host, "port": port, "debug": debug}:
            return f"服务器: {host}:{port}, 调试={'开' if debug else '关'}"
        case {"database": db_config}:
            return f"数据库配置: {db_config}"
        case {}:
            return "空配置"
        case _:
            return "无效配置"

print(analyze_config({"host": "localhost", "port": 8080}))
# 服务器: localhost:8080

print(analyze_config({"host": "0.0.0.0", "port": 443, "debug": True}))
# 服务器: 0.0.0.0:443, 调试=开

# ⚠️ 注意匹配顺序!上面的例子有个bug:
# {"host": host, "port": port} 会先匹配,即使有debug键也会进入第一个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 {"database": db_config}:
            return f"数据库配置: {db_config}"
        case _:
            return "无效配置"

3.3 匹配类实例

# 匹配自定义类的实例
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class Circle:
    def __init__(self, center, radius):
        self.center = center
        self.radius = radius

class Rectangle:
    def __init__(self, top_left, bottom_right):
        self.top_left = top_left
        self.bottom_right = bottom_right

def describe_shape(shape):
    match shape:
        case Point(x=0, y=0):
            return "原点"
        case Point(x=x, y=y):
            return f"点({x}, {y})"
        case Circle(center=Point(x=x, y=y), radius=r):
            return f"圆: 圆心({x}, {y}), 半径{r}"
        case Rectangle(top_left=Point(x=x1, y=y1), bottom_right=Point(x=x2, y=y2)):
            return f"矩形: ({x1},{y1}) 到 ({x2},{y2})"
        case _:
            return "未知形状"

# 使用
p1 = Point(0, 0)
p2 = Point(3, 4)
c = Circle(Point(1, 2), 5)
r = Rectangle(Point(0, 0), Point(10, 10))

print(describe_shape(p1))   # 原点
print(describe_shape(p2))   # 点(3, 4)
print(describe_shape(c))    # 圆: 圆心(1, 2), 半径5
print(describe_shape(r))    # 矩形: (0,0) 到 (10,10)

四、守卫条件(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):        # n == 0
            return "零"
        case float(f) if f > 0:
            return f"正浮点数: {f}"
        case float(f) if f < 0:
            return f"负浮点数: {f}"
        case float(f):
            return "浮点数零"
        case str(s) if len(s) > 10:
            return f"长字符串({len(s)}字符): {s[:10]}..."
        case str(s):
            return f"短字符串: {s}"
        case _:
            return "其他类型"

print(classify_value(42))           # 正整数: 42
print(classify_value(-3.14))        # 负浮点数: -3.14
print(classify_value("Hello"))      # 短字符串: Hello
print(classify_value("Hello World! This is Python"))  # 长字符串(28字符)

# 结合守卫和OR模式
def check_age(age):
    match age:
        case int(n) if n < 0 | n > 150:
            return "无效年龄"
        case int(n) if n < 18:
            return "未成年人"
        case int(n) if n < 65:
            return "成年人"
        case int(n):
            return "老年人"
        case _:
            return "非数字输入"

五、match-case vs if-elif-else

5.1 什么时候用match-case

# ✅ 适合match-case:基于值的多分支选择
def get_day_type(day):
    match day.lower():
        case "monday" | "tuesday" | "wednesday" | "thursday" | "friday":
            return "工作日"
        case "saturday" | "sunday":
            return "周末"
        case _:
            return "未知"

# ✅ 适合match-case:解构复杂数据结构
def process_api_response(response):
    match response:
        case {"status": "ok", "data": data}:
            return handle_data(data)
        case {"status": "error", "message": msg}:
            return f"错误: {msg}"
        case {"status": "error", "code": int(code)} if code >= 500:
            return f"服务器错误([code])"
        case {"status": "error", "code": int(code)}:
            return f"客户端错误([code])"
        case _:
            return "未知响应格式"

# ❌ 不适合match-case:需要复杂比较逻辑
# 这种情况下if-elif-else更合适
def analyze_score(score):
    # if-elif-else更合适
    if score >= 90:
        return "优秀"
    elif score >= 80:
        return "良好"
    elif score >= 70:
        return "中等"
    else:
        return "需要提升"

5.2 两者的混合使用

# match-case 和 if-elif-else 可以混合
def smart_classifier(obj):
    # 先用match-case按类型分大类
    match obj:
        case int(n):
            # 再用if-elif按范围细分
            if n < 0:
                return "负整数"
            elif n == 0:
                return "零"
            elif n < 10:
                return "小正整数"
            else:
                return "大正整数"
        
        case str(s):
            if len(s) == 0:
                return "空字符串"
            elif len(s) < 10:
                return "短字符串"
            else:
                return "长字符串"
        
        case list(items):
            if len(items) == 0:
                return "空列表"
            elif all(isinstance(i, int) for i in items):
                return "整数列表"
            else:
                return "混合列表"
        
        case _:
            return f"不支持的类型: {type(obj).__name__}"

六、实战案例

6.1 JSON数据验证与解析

def parse_user_data(data):
    """解析并验证用户数据"""
    match data:
        # 完整数据
        case {
            "name": str(name),
            "age": int(age),
            "email": str(email),
            **extra      # **extra 收集额外字段
        } if 0 < age < 150 and "@" in email:
            result = {
                "name": name,
                "age": age,
                "email": email,
                "valid": True,
            }
            if extra:
                result["extra_fields"] = list(extra.keys())
            return result
        
        # 缺少email但有name和age
        case {"name": str(name), "age": int(age)} if 0 < age < 150:
            return {
                "name": name,
                "age": age,
                "valid": True,
                "warnings": ["缺少邮箱地址"],
            }
        
        # 只有name
        case {"name": str(name)}:
            return {
                "name": name,
                "valid": False,
                "errors": ["缺少年龄和邮箱"],
            }
        
        # 空数据或格式不对
        case dict():
            return {"valid": False, "errors": ["数据格式不正确"]}
        
        case _:
            return {"valid": False, "errors": ["输入不是字典类型"]}

# 测试
test_cases = [
    {"name": "张三", "age": 25, "email": "zhangsan@example.com", "city": "北京"},
    {"name": "李四", "age": 30},
    {"name": "王五"},
    {"invalid": "data"},
    "not a dict",
]

for data in test_cases:
    result = parse_user_data(data)
    print(f"\n输入: {data}")
    print(f"输出: {result}")

6.2 简易计算器

def calculator():
    """命令行计算器,展示match-case的模式匹配能力"""
    print("简易计算器(输入 'quit' 退出)")
    print("支持格式:<数字> <操作符> <数字>")
    print("示例:10 + 20, 3.14 * 2, 100 / 4")
    
    while True:
        user_input = input("\n> ").strip()
        
        if not user_input:
            continue
        
        match user_input.split():
            case ["quit" | "exit" | "q"]:
                print("再见!")
                break
            
            case ["help" | "h" | "?"]:
                print("操作符: + (加), - (减), * (乘), / (除), ** (幂), % (取模)")
                print("输入 'quit' 退出, 'clear' 清零")
            
            case ["clear" | "c"]:
                print("计算器已重置")
            
            case [left, op, right]:
                try:
                    a, b = float(left), float(right)
                    match op:
                        case "+":
                            result = a + b
                        case "-":
                            result = a - b
                        case "*" | "×" | "x":
                            result = a * b
                        case "/" | "÷":
                            if b == 0:
                                print("❌ 除数不能为零!")
                                continue
                            result = a / b
                        case "**" | "^":
                            result = a ** b
                        case "%":
                            result = a % b
                        case _:
                            print(f"❌ 未知操作符: {op}")
                            continue
                    print(f"  {a} {op} {b} = {result}")
                except ValueError:
                    print("❌ 请输入有效的数字")
            
            case _:
                print("❌ 格式错误,请使用: <数字> <操作符> <数字>")

# 运行计算器(取消注释使用)
# calculator()

6.3 抽象语法树处理器

# 用match-case处理简单的表达式树
class Expr:
    pass

class Number(Expr):
    def __init__(self, value):
        self.value = value

class BinOp(Expr):
    def __init__(self, left, op, right):
        self.left = left
        self.op = op
        self.right = right

class UnaryOp(Expr):
    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 BinOp(left=l, op="*", right=r):
            return evaluate(l) * evaluate(r)
        
        case BinOp(left=l, op="/", right=r):
            divisor = evaluate(r)
            if divisor == 0:
                raise ZeroDivisionError("除数不能为零")
            return evaluate(l) / divisor
        
        case UnaryOp(op="-", operand=opd):
            return -evaluate(opd)
        
        case UnaryOp(op="+", operand=opd):
            return evaluate(opd)
        
        case _:
            raise ValueError(f"未知表达式: {expr}")

# 构建表达式: (-5 + 3) * 2
expr = BinOp(
    BinOp(UnaryOp("-", Number(5)), "+", Number(3)),
    "*",
    Number(2)
)
print(f"(-5 + 3) * 2 = {evaluate(expr)}")    # -4

七、本章小结

本文我们学习了Python 3.10的match-case模式匹配语句:

基本语法match subject: case pattern: ... case _: ..._是通配符。

OR模式case 1 | 2 | 3: 匹配多个值。

变量绑定case ["add", x, y]: 在匹配时提取值到变量。

结构化匹配(核心特性):

  • 序列:[first, *rest][first, *middle, last]
  • 映射:{"key": value_pattern, **rest}
  • 类实例:Point(x=x, y=y)

守卫条件case pattern if condition: 在模式匹配基础上加条件。

选型建议:match-case适合值匹配和结构解构,if-elif-else适合范围比较。两者可以混合使用。

match-case是Python 3.10最重大的新特性。掌握了它,你处理复杂分支逻辑的能力将上升一个台阶。⌨️ 下一篇文章,我们将进入循环的世界——从while循环开始!

以上就是Python基础指南之match-case模式匹配语句的使用教学的详细内容,更多关于Python match-case语句使用的资料请关注脚本之家其它相关文章!

相关文章

  • python使用xlsx和pandas处理Excel表格的操作步骤

    python使用xlsx和pandas处理Excel表格的操作步骤

    python的神器pandas库就可以非常方便地处理excel,csv,矩阵,表格 等数据,下面这篇文章主要给大家介绍了关于python使用xlsx和pandas处理Excel表格的操作步骤,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • python实现dnspod自动更新dns解析的方法

    python实现dnspod自动更新dns解析的方法

    这篇文章主要介绍了python实现的dnspod自动更新dns解析的方法,需要的朋友可以参考下
    2014-02-02
  • pandas中的Timestamp只保留日期不显示时间

    pandas中的Timestamp只保留日期不显示时间

    这篇文章主要介绍了pandas中的Timestamp只保留日期不显示时间,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Python判断某个用户对某个文件的权限

    Python判断某个用户对某个文件的权限

    这篇文章主要为大家详细介绍了Python如何判断某个用户对某个文件的权限,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Python基于socket实现TCP/IP客户和服务器通信

    Python基于socket实现TCP/IP客户和服务器通信

    本主要介绍了Python socket网络编程TCP/IP服务器与客户端通信的相关资料,这里对Scoket 进行详解并创建TCP服务器及TCP 客户端实例代码,需要的朋友可以参考下
    2021-06-06
  • flask-socketio实现前后端实时通信的功能的示例

    flask-socketio实现前后端实时通信的功能的示例

    本文主要介绍了flask-socketio实现前后端实时通信的功能的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Python字典数据对象拆分的简单实现方法

    Python字典数据对象拆分的简单实现方法

    这篇文章主要介绍了Python字典数据对象拆分的简单实现方法,涉及Python针对字典数据的相关遍历、拆分等操作技巧,需要的朋友可以参考下
    2017-12-12
  • Python Requests库及用法详解

    Python Requests库及用法详解

    Requests库作为Python中最受欢迎的HTTP库之一,为开发人员提供了简单而强大的方式来发送HTTP请求和处理响应,本文将带领您深入探索Python Requests库的世界,我们将从基础知识开始,逐步深入,覆盖各种高级用法和技巧,感兴趣的朋友一起看看吧
    2024-06-06
  • PyInstaller的安装和使用的详细步骤

    PyInstaller的安装和使用的详细步骤

    这篇文章主要介绍了PyInstaller的安装和使用的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • Python 使用csv库处理CSV文件的方法

    Python 使用csv库处理CSV文件的方法

    Python中集成了专用于处理csv文件的库,名为:csv,本文给大家介绍了Python使用csv库处理CSV文件的方法及csv库中4个常用的对象,结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-06-06

最新评论