Python & AI Tutorials Logo
Python 编程

13. 使用 match 和 case 做选择(结构化模式匹配)

当你的程序需要基于多个可能的值或模式来做决策时,你已经在第 8 章学习了使用 if-elif-else 链。Python 3.10 引入了一种强大的替代方案,称为使用 matchcase 语句的结构化模式匹配(structural pattern matching)。这个特性提供了一种更简洁、更具表达力的方式来处理复杂的决策场景。

模式匹配(pattern matching)不止是简单的值比较。它允许你针对数据的结构与形状进行匹配,从复杂对象中提取值,并以更易读的形式表达多路决策(multi-way decisions)。虽然 if-elif-else 链在很多情况下都完全够用,但当你需要处理多个彼此不同的分支,尤其是在处理结构化数据时,match-case 语句就会大放异彩。

13.1) 介绍 match 和 case 语句(在第 8 章 if-elif 的基础上)

13.1.1) match-case 的基本结构

match 语句会检查一个值(称为主体(subject)),并将其与 case 子句中定义的一个或多个模式(pattern)进行比较。当某个模式匹配时,Python 会执行与该 case 关联的代码块。

基本结构如下:

python
match subject:
    case pattern1:
        # 如果 pattern1 匹配则执行的代码
    case pattern2:
        # 如果 pattern2 匹配则执行的代码
    case pattern3:
        # 如果 pattern3 匹配则执行的代码

让我们从一个简单示例开始,来演示基本概念:

python
# 简单的 HTTP 状态码处理器
status_code = 404
 
match status_code:
    case 200:
        print("Success: Request completed")
    case 404:
        print("Error: Page not found")
    case 500:
        print("Error: Server error")

Output:

Error: Page not found

在这个示例中,match 语句检查 status_code(主体)。Python 会按顺序检查每个 case 模式。当它发现 status_code 等于 404 时,就执行对应的代码块,然后退出 match 语句。剩余的 case 不会再被检查。

13.1.2) match-case 与 if-elif-else 有何不同

你可能会想:“我不能用 if-elif-else 来写吗?”可以,你当然可以:

python
status_code = 404
 
if status_code == 200:
    print("Success: Request completed")
elif status_code == 404:
    print("Error: Page not found")
elif status_code == 500:
    print("Error: Server error")

Output:

Error: Page not found

两种写法都会产生相同的结果。不过,match-case 有几个优势:

  1. 意图更清晰match 语句明确表明你是在用一个值去对比多个可能性
  2. 重复更少:你不需要在每次比较里重复写变量名
  3. 模式更强大:正如我们将看到的,match-case 能做的不只是简单的相等判断
  4. 可读性更好:对于复杂的决策树,match-case 往往更容易理解

13.1.3) 当没有模式匹配时

如果没有任何模式匹配,会发生什么?match 语句会直接结束,不会执行任何 case 块:

python
# 用户角色检查器
user_role = "guest"
 
match user_role:
    case "admin":
        print("Full system access granted")
    case "moderator":
        print("Content management access granted")
    case "editor":
        print("Editing access granted")
 
print("Role check complete")

Output:

Role check complete

由于 "guest" 不匹配任何模式,因此不会执行任何 case 块。程序会继续执行 match 语句之后的代码。理解这个行为很重要——不同于 if-elif-else 链,你可以添加最后一个 else 子句来捕获所有其他情况;而一个没有兜底模式的基础 match 语句在没有任何模式匹配时会“静默地”不做任何事。

13.1.4) 实用示例:菜单选择系统

我们来构建一个更完整的示例,展示 match-case 在处理用户选择时的清晰性:

python
# 餐厅点餐系统
menu_choice = 3
 
match menu_choice:
    case 1:
        item = "Caesar Salad"
        price = 8.99
        print(f"You ordered: {item} - ${price}")
    case 2:
        item = "Grilled Chicken"
        price = 14.99
        print(f"You ordered: {item} - ${price}")
    case 3:
        item = "Vegetable Pasta"
        price = 12.99
        print(f"You ordered: {item} - ${price}")
    case 4:
        item = "Chocolate Cake"
        price = 6.99
        print(f"You ordered: {item} - ${price}")
 
print("Order submitted to kitchen")

Output:

You ordered: Vegetable Pasta - $12.99
Order submitted to kitchen

这个示例展示了每个 case 中可以包含多条语句。当 menu_choice 匹配 3 时,Python 会执行该 case 块中的三行:给 item 赋值、给 price 赋值、并打印订单确认信息。

13.2) 使用 _ 通配符、字面量模式与多重模式

13.2.1) 通配符模式:捕获所有其他情况

下划线 _ 是一种特殊模式,可以匹配任何东西。它通常用作最后一个 case,用来处理所有未匹配前面模式的值——类似于 if-elif-else 链中的最终 else 子句:

python
# 带默认分支的 HTTP 状态码处理器
status_code = 403
 
match status_code:
    case 200:
        print("Success: Request completed")
    case 404:
        print("Error: Page not found")
    case 500:
        print("Error: Server error")
    case _:
        print(f"Unhandled status code: {status_code}")

Output:

Unhandled status code: 403

_ 模式充当兜底分支。由于 403 不匹配任何特定 case,通配符模式会匹配并执行其代码块。通配符模式会匹配任何值,因此它应当总是放在最后——放在它之后的任何 case 都永远不会执行。

下面说明为什么通配符在实践中很有用:

python
# 星期日程安排器
day = "Saturday"
 
match day:
    case "Monday":
        print("Team meeting at 9 AM")
    case "Wednesday":
        print("Project review at 2 PM")
    case "Friday":
        print("Weekly report due")
    case _:
        print(f"{day}: No scheduled events")

Output:

Saturday: No scheduled events

如果没有通配符模式,当 day"Saturday""Sunday" 或任何其他值时,match 语句会静默结束且没有输出。通配符可以确保你能优雅地处理意外或未指定的情况。

13.2.2) 字面量模式:匹配特定值

字面量模式(literal patterns)会匹配精确的值。我们已经在使用它们——数字、字符串、布尔值都是字面量模式:

python
# 交通灯控制器
light_color = "yellow"
 
match light_color:
    case "green":
        print("Go")
    case "yellow":
        print("Caution: Light changing soon")
    case "red":
        print("Stop")
    case _:
        print("Invalid light color")

Output:

Caution: Light changing soon

你可以使用不同类型的字面量模式,并且 match 会同时比较值及其类型:

python
# 配置校验器(使用不同的字面量类型)
setting_value = True
 
match setting_value:
    case True:        # 布尔字面量
        print("Feature enabled")
    case False:       # 布尔字面量
        print("Feature disabled")
    case None:        # None 字面量
        print("Feature not configured")
    case 0:           # 整数字面量
        print("Feature explicitly turned off")
    case "auto":      # 字符串字面量
        print("Feature set to automatic mode")
    case _:
        print("Invalid configuration value")

Output:

Feature enabled

字面量模式可用于整数、浮点数、字符串、布尔值以及 None。Python 会使用与 == 运算符相同的规则来检查相等性。

13.2.3) 使用 OR 运算符匹配多个模式

有时你希望针对多个不同值执行同一段代码。你可以使用 |(管道符)运算符来组合多个模式,它表示“或”:

python
# 周末检测器
day = "Saturday"
 
match day:
    case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday":
        print("It's a weekday - time to work!")
    case "Saturday" | "Sunday":
        print("It's the weekend - time to relax!")
    case _:
        print("Invalid day name")

Output:

It's the weekend - time to relax!

| 运算符允许你指定多个模式来触发同一行为。如果主体与 | 分隔的任一模式匹配,该 case 就会执行。这比写多个带相同代码块的独立 case 清爽得多。

你也可以用 | 混合不同类型的模式:

python
# yes/no 问题的输入校验器
response = "yes"
 
match response:
    case True | "yes":
        print("You confirmed the action")
    case False | "no":
        print("You cancelled the action")
    case _:
        print("Please answer yes or no")

Output:

You confirmed the action

13.2.4) 用 as 捕获匹配到的具体分支

当你使用 | 匹配多个模式时,你可能想知道到底是哪个具体值匹配了。你可以用 as 关键字来捕获匹配到的值:

python
# 按分组处理响应的状态码处理器
status = 201
 
match status:
    case 200 | 201 | 202 | 204 as success_code:
        print(f"Success: {success_code}")
    case 400 | 401 | 403 | 404 as client_error:
        print(f"Client error: {client_error}")
    case 500 | 502 | 503 as server_error:
        print(f"Server error: {server_error}")
    case _:
        print("Unknown status code")

Output:

Success: 201

as 关键字会创建一个绑定变量(binding variable),用于捕获匹配到的具体备选项。在这个例子中,success_code 绑定为 201,因为在备选项 200 | 201 | 202 | 204 中,具体匹配到的是 201

下面是另一个示例,展示这在日志记录中如何有用:

python
# 日志级别处理器
log_level = "WARN"
 
match log_level:
    case "DEBUG" | "TRACE" as level:
        print(f"Verbose logging: {level}")
        print("Detailed diagnostic information will be recorded")
    case "INFO" | "NOTICE" as level:
        print(f"Informational: {level}")
        print("Normal operation messages will be recorded")
    case "WARN" | "WARNING" as level:
        print(f"Warning level: {level}")
        print("Potential issues detected")
    case "ERROR" | "FATAL" | "CRITICAL" as level:
        print(f"Error level: {level}")
        print("Immediate attention required")
    case _:
        print("Unknown log level")

Output:

Warning level: WARN
Potential issues detected

13.3) 使用绑定变量提取值

13.3.1) 什么是绑定变量?

到目前为止,我们都是在匹配字面量值。但当你能捕获(capture)提取(extract)被匹配数据的一部分时,模式匹配才真正强大。绑定变量(binding variable)(也称为捕获模式(capture pattern))是在模式中出现的一个名字,它会捕获匹配到的值,并让你在 case 块中使用它。

下面是一个简单示例:

python
# 简单的值捕获
command = "save"
 
match command:
    case "quit":
        print("Exiting program")
    case action:  # 这是一个绑定变量
        print(f"Executing action: {action}")

Output:

Executing action: save

模式 action 是一个绑定变量。它可以匹配任何值(像通配符 _ 一样),但与 _ 不同的是,它会捕获该值并将其赋给名字 action。在 case 块内部,你可以使用 action 来引用匹配到的值。

重要区别:绑定变量会匹配任何东西,就像 _ 一样。区别在于:_ 会丢弃这个值,而绑定变量会捕获它,以便在 case 块中使用。

13.3.2) 绑定变量 vs 通配符

我们来直接对比绑定变量和通配符:

python
# 使用通配符——不会捕获值
status = 403
 
match status:
    case 200:
        print("Success")
    case _:
        print("Some other status code")  # 无法访问实际值

Output:

Some other status code

现在换成绑定变量:

python
# 使用绑定变量——会捕获值
status = 403
 
match status:
    case 200:
        print("Success")
    case code:  # 绑定变量捕获该值
        print(f"Status code {code} received")

Output:

Status code 403 received

绑定变量 code 捕获了值 403,使其在 case 块中可用。当你需要处理未匹配特定模式的实际值时,这非常有用。

13.3.3) 匹配元组模式并提取组成部分

对于像元组(tuple)这样的结构化数据,模式匹配会变得格外强大。你可以在匹配元组形状的同时提取其组成部分。虽然我们会在第 15 章详细学习元组,但这个示例只关注元组模式在 match 语句中的工作方式。

python
# 坐标系统——匹配元组模式
point = (3, 7)
 
match point:
    case (0, 0):
        print("Origin point")
    case (0, y):  # 匹配 y 轴上的任意点
        print(f"On y-axis at y={y}")
    case (x, 0):  # 匹配 x 轴上的任意点
        print(f"On x-axis at x={x}")
    case (x, y):  # 匹配其他任意点
        print(f"Point at coordinates ({x}, {y})")

Output:

Point at coordinates (3, 7)

让我们分解一下发生了什么:

  1. 主体 point 是元组 (3, 7)
  2. Python 按顺序检查每个 case 模式
  3. 前三个模式都不匹配,因为它们要求在特定位置出现值 0,而元组 (3, 7) 没有任何元素等于 0
  4. 模式 (x, y) 匹配,因为它是一个包含两个元素的元组
  5. Python 将 x 绑定为 3,将 y 绑定为 7
  6. case 块使用这些捕获到的值执行

下面是另一个示例,展示不同的元组模式:

python
# RGB 颜色分析器
color = (255, 0, 0)
 
match color:
    case (0, 0, 0):
        print("Black")
    case (255, 255, 255):
        print("White")
    case (r, 0, 0):  # 纯红,强度可变
        print(f"Pure red with intensity {r}")
    case (0, g, 0):  # 纯绿
        print(f"Pure green with intensity {g}")
    case (0, 0, b):  # 纯蓝
        print(f"Pure blue with intensity {b}")
    case (r, g, b):  # 其他任意颜色
        print(f"RGB color: red={r}, green={g}, blue={b}")

Output:

Pure red with intensity 255

这个输入匹配模式 (r, 0, 0),因为元组有三个元素,后两个是 0,第一个值被绑定到 r

13.3.4) 匹配列表模式

你也可以匹配列表(list)模式并提取元素。我们会在第 14 章详细讲列表;现在,这个示例只关注列表模式在 match 语句中的工作方式:

python
# 带参数的命令
command = ["move", "north", "5"]
 
match command:
    case ["quit"]:
        print("Exiting game")
    case ["look"]:
        print("You look around the room")
    case ["move", direction]:
        print(f"Moving {direction}")
    case ["move", direction, distance]:
        print(f"Moving {direction} for {distance} steps")
    case _:
        print("Unknown command")

Output:

Moving north for 5 steps

模式 ["move", direction, distance] 匹配一个三元素列表,且第一个元素是 "move"。它会把第二个元素捕获为 direction,把第三个捕获为 distance

下面是一个更实用的示例,处理不同长度的列表:

python
# 购物车条目处理器
item = ["laptop", 999.99, 2]
 
match item:
    case [name]:  # 只有名称的条目
        print(f"Item: {name} (no price or quantity specified)")
    case [name, price]:  # 带名称与价格的条目
        print(f"Item: {name}, Price: ${price}, Quantity: 1 (default)")
    case [name, price, quantity]:  # 完整条目信息
        total = price * quantity
        print(f"Item: {name}, Price: ${price}, Quantity: {quantity}")
        print(f"Subtotal: ${total}")
    case _:
        print("Invalid item format")

Output:

Item: laptop, Price: $999.99, Quantity: 2
Subtotal: $1999.98

由于列表正好有三个元素,case [name, price, quantity] 会执行,并且每个元素都会绑定到其对应变量。

13.3.5) 匹配字典模式

模式匹配也适用于字典(dictionary),允许你匹配特定键并提取其值。虽然我们会在第 16 章详细学习字典,但本节只关注字典模式在 match 语句中的工作方式。

python
# 用户资料处理器
user = {"name": "Alice", "role": "admin", "active": True}
 
match user:
    case {"role": "admin", "active": True}:
        print("Active administrator - full access granted")
    case {"role": "admin", "active": False}:
        print("Inactive administrator - access suspended")
    case {"role": role, "active": True}:  # 捕获 role 的值
        print(f"Active user with role: {role}")
    case {"role": role, "active": False}:
        print(f"Inactive user with role: {role}")
    case _:
        print("Invalid user profile")

Output:

Active administrator - full access granted

由于字典模式要求匹配键值对,并且在更通用的模式之前会先检查精确匹配,因此会执行 {"role": "admin", "active": True} 这一分支。

字典模式很灵活——只要指定的键存在且对应值匹配,即使字典还有额外键也能匹配:

python
# API 响应处理器
response = {"status": "success", "data": {"id": 123, "name": "Product"}, "timestamp": "2025-12-17"}
 
match response:
    case {"status": "error", "message": msg}:
        print(f"Error occurred: {msg}")
    case {"status": "success", "data": data}:
        print(f"Success! Data received: {data}")
    case _:
        print("Unknown response format")

Output:

Success! Data received: {'id': 123, 'name': 'Product'}

尽管字典还有额外的 "timestamp" 键,模式 {"status": "success", "data": data} 仍然可以匹配。该模式只要求指定的键存在,并且对应的值(或模式)匹配即可。

13.3.6) 组合字面量与绑定变量

你可以混用字面量模式与绑定变量来创建更复杂的匹配逻辑: 不同于前面元组示例主要强调结构与位置匹配,这个示例展示如何将字面量值与绑定变量组合起来,以实现真实世界的决策逻辑。

python
# HTTP 请求路由器
request = ("GET", "/api/users", 42)
 
match request:
    case ("GET", "/", None):
        print("Homepage request")
    case ("GET", path, None):
        print(f"GET request for: {path}")
    case ("POST", path, data):
        print(f"POST request to {path} with data: {data}")
    case ("GET", path, user_id):
        print(f"GET request for {path} with user ID: {user_id}")
    case _:
        print("Unsupported request type")

Output:

GET request for /api/users with user ID: 42

这个示例展示了你可以在同一个模式中匹配特定值(比如 "GET"),同时捕获其他部分(比如 pathuser_id)。

13.3.7) 实用示例:事件处理器

我们来构建一个完整示例,展示绑定变量的威力:

python
# 游戏事件处理器
event = ("player_move", {"x": 10, "y": 5, "speed": 2})
 
match event:
    case ("player_move", {"x": x, "y": y}):
        print(f"Player moved to position ({x}, {y})")
    case ("player_attack", {"target": target, "damage": damage}):
        print(f"Player attacked {target} for {damage} damage")
    case ("item_pickup", {"item": item_name}):
        print(f"Player picked up: {item_name}")
    case ("game_over", {"score": final_score}):
        print(f"Game ended. Final score: {final_score}")
    case (event_type, data):
        print(f"Unknown event type: {event_type}")
        print(f"Event data: {data}")

Output:

Player moved to position (10, 5)

这个事件处理器匹配包含事件类型与事件数据字典的元组。它会根据事件类型从字典中提取特定值,让你可以用干净、可读的代码处理不同类型的事件。

13.4) 使用 if 守卫条件添加额外条件

13.4.1) 什么是守卫条件?

有时你需要匹配某个模式,并且检查一个额外条件。if 守卫条件(if guard)是你可以用 if 关键字添加到 case 模式上的额外条件。只有当模式匹配并且守卫条件为真时,该 case 才会匹配。

语法如下:

python
match subject:
    case pattern if condition:
        # 仅当 pattern 匹配且 condition 为 True 时才执行

让我们看一个简单示例:

python
# 基于年龄的访问控制
age = 16
 
match age:
    case age if age >= 18:
        print("Adult - full access granted")
    case age if age >= 13:
        print("Teen - limited access granted")
    case age if age >= 0:
        print("Child - parental supervision required")
    case _:
        print("Invalid age")

Output:

Teen - limited access granted

在这个示例中,绑定变量 age 捕获了值,而守卫 if age >= 13 添加了额外条件。该 case 只有在值大于等于 13 时才匹配。由于 age16,第二个 case 匹配并执行。

13.4.2) 守卫条件如何被求值

理解求值顺序很重要。下面是一个详细的可视化,展示守卫条件如何与模式匹配交互:

检查 case 模式

模式匹配吗?

尝试下一个 case

求值守卫条件

守卫为 True 吗?

执行 case 代码块

退出 match 语句

还有更多 case 吗?

未找到匹配 - 在 match 之后继续

Python 会先检查模式是否匹配。只有当模式匹配时,Python 才会计算守卫条件。如果守卫为假,Python 会跳到下一个 case——即使模式本身是匹配的。

下面是一个能体现这一点的示例:

python
# 温度预警系统
temperature = 25
 
match temperature:
    case temp if temp > 35:
        print(f"Extreme heat warning: {temp}°C")
    case temp if temp > 30:
        print(f"High temperature alert: {temp}°C")
    case temp if temp > 20:
        print(f"Comfortable temperature: {temp}°C")
    case temp if temp > 10:
        print(f"Cool temperature: {temp}°C")
    case temp:
        print(f"Cold temperature: {temp}°C")

Output:

Comfortable temperature: 25°C

每个 case 都用绑定变量 temp 捕获温度值,然后用守卫检查它是否落在特定范围内。case 会按顺序检查,因此第一个“模式匹配且守卫为真”的分支会执行。

13.4.3) 带字面量模式的守卫条件

你可以把守卫条件与字面量模式结合起来,创建更具体的匹配:

python
# 基于商品类型和数量的折扣计算器
item = ("book", 5)
 
match item:
    case ("book", quantity) if quantity >= 10:
        discount = 0.20  # 10 本及以上书籍享受 20% 折扣
        print(f"Bulk book order: {quantity} books, {discount*100}% discount")
    case ("book", quantity) if quantity >= 5:
        discount = 0.10  # 5-9 本书籍享受 10% 折扣
        print(f"Book order: {quantity} books, {discount*100}% discount")
    case ("book", quantity):
        discount = 0.0  # 少于 5 本不打折
        print(f"Book order: {quantity} books, no discount")
    case (item_type, quantity):
        print(f"Order: {quantity} {item_type}(s)")

Output:

Book order: 5 books, 10.0% discount

模式 ("book", quantity) 匹配一个元组,其第一个元素为 "book"。守卫 if quantity >= 5 增加了条件:数量必须至少为 5。

13.4.4) 复杂条件的守卫

守卫条件可以使用任何布尔表达式,包括使用 andornot 的复杂条件:

python
# 考虑出勤率的学生成绩评估器
student = {"name": "Bob", "grade": 85, "attendance": 75}
 
match student:
    case {"grade": g, "attendance": a} if g >= 90 and a >= 90:
        status = "Excellent"
        print(f"Grade: {g}, Attendance: {a}% - Status: {status}")
    case {"grade": g, "attendance": a} if g >= 80 and a >= 80:
        status = "Good"
        print(f"Grade: {g}, Attendance: {a}% - Status: {status}")
    case {"grade": g, "attendance": a} if g >= 70 and a >= 70:
        status = "Satisfactory"
        print(f"Grade: {g}, Attendance: {a}% - Status: {status}")
    case {"grade": g, "attendance": a} if g >= 60 or a >= 60:
        status = "Needs Improvement"
        print(f"Grade: {g}, Attendance: {a}% - Status: {status}")
    case _:
        print("Failing - immediate intervention required")

Output:

Grade: 85, Attendance: 75% - Status: Satisfactory

守卫 if g >= 70 and a >= 70 要求成绩和出勤率都至少为 70。由于 Bob 的成绩是 85 且出勤率是 75%,该 case 匹配并执行。

13.4.5) 实用示例:用户认证系统

我们来构建一个完整示例,使用守卫条件实现一个现实的认证系统:

python
# 带基于角色访问控制的用户认证
user = {"username": "alice", "role": "admin", "active": True, "login_attempts": 0}
 
match user:
    case {"active": False}:
        print("Account suspended - contact administrator")
    case {"login_attempts": attempts} if attempts >= 3:
        print("Account locked due to too many failed login attempts")
    case {"role": "admin", "active": True}:
        print("Admin access granted - full system privileges")
    case {"role": "moderator", "active": True}:
        print("Moderator access granted - content management privileges")
    case {"role": role, "active": True} if role in ["editor", "author"]:
        print(f"{role.capitalize()} access granted - content creation privileges")
    case {"role": "user", "active": True}:
        print("User access granted - basic privileges")
    case _:
        print("Access denied - invalid user profile")

Output:

Admin access granted - full system privileges

这个示例展示了守卫条件如何实现复杂的业务逻辑。系统会检查多个条件:账号状态、登录尝试次数以及基于角色的权限。每个 case 处理一种特定场景,使认证逻辑清晰且易维护。

13.5) 匹配简单序列与映射的形状

13.5.1) 匹配可变长度序列

有时你需要匹配长度不固定的序列。Python 的模式匹配通过 * 运算符支持这一点,它会捕获零个或多个元素。

python
# 支持可变参数的命令解析器
command = ["copy", "file1.txt", "file2.txt", "file3.txt", "backup/"]
 
match command:
    case ["help"]:
        print("Available commands: copy, move, delete")
    case ["copy", source, destination]:
        print(f"Copying {source} to {destination}")
    case ["copy", *sources, destination]:
        print(f"Copying {len(sources)} files to {destination}")
        print(f"Source files: {sources}")
    case ["delete", *files]:
        print(f"Deleting {len(files)} file(s): {files}")
    case _:
        print("Unknown command")

Output:

Copying 3 files to backup/
Source files: ['file1.txt', 'file2.txt', 'file3.txt']

模式 ["copy", *sources, destination] 匹配一个以 "copy" 开头、以 destination 结尾,并且中间包含任意数量源文件的列表。*sources 会把中间所有元素捕获为一个列表。

重要:每个序列模式中只能使用一个 * 模式,并且它会以列表形式捕获元素:

python
# 日志条目解析器
log_entry = ["2025-12-17", "10:30:45", "ERROR", "Database", "connection", "timeout"]
 
match log_entry:
    case [date, time, "ERROR", *error_details]:
        print(f"Error on {date} at {time}")
        print(f"Error details: {' '.join(error_details)}")
    case [date, time, "WARNING", *warning_details]:
        print(f"Warning on {date} at {time}")
        print(f"Warning details: {' '.join(warning_details)}")
    case [date, time, level, *message]:
        print(f"{level} on {date} at {time}: {' '.join(message)}")

Output:

Error on 2025-12-17 at 10:30:45
Error details: Database connection timeout

13.5.2) 将序列模式与守卫条件结合

你可以将守卫条件与序列模式结合,以添加额外约束:

python
# 成绩列表分析器
grades = [85, 92, 78, 95, 88]
 
match grades:
    case []:
        print("No grades recorded")
    case [grade] if grade >= 90:
        print(f"Single excellent grade: {grade}")
    case [grade] if grade < 60:
        print(f"Single failing grade: {grade}")
    case [*all_grades] if len(all_grades) >= 5 and sum(all_grades) / len(all_grades) >= 90:
        average = sum(all_grades) / len(all_grades)
        print(f"Excellent performance! Average: {average:.1f}")
    case [*all_grades] if len(all_grades) >= 5:
        average = sum(all_grades) / len(all_grades)
        print(f"Performance review: {len(all_grades)} grades, Average: {average:.1f}")
    case [*all_grades]:
        print(f"Insufficient data: only {len(all_grades)} grade(s)")

Output:

Performance review: 5 grades, Average: 87.6

模式 [*all_grades] 会捕获列表中的所有元素,而守卫会同时检查长度并计算平均值,从而确定应输出的消息。


使用 matchcase 的模式匹配,为你在 Python 中处理复杂决策提供了一种强大且富有表达力的方式。从简单的值匹配,到带守卫条件的复杂结构化模式,这个特性让你能写出更简洁、更易维护的代码,用于处理多种情况并从复杂结构中提取数据。

随着你继续学习 Python,你会发现模式匹配可以补充你在第 8 章学到的条件逻辑,在面对多个彼此不同的分支时,尤其是在处理结构化数据时,它提供了一种优雅的替代方案。关键在于为每种情境选择合适工具:简单条件与布尔逻辑用 if-elif-else,而当你需要将一个值与多个可能性对照,或处理需要基于模式提取的结构化数据时,就选择 match-case


© 2025. Primesoft Co., Ltd.
support@primesoft.ai