如何在 Python 3.10 中使用 match-case 语句

更新于 2026-01-12

Luke Hande 2022-05-09

Python 编程语言持续不断地发展,每次更新都会引入新特性和功能。Python 3.10 于 2021 年年中发布,带来了结构化模式匹配(structural pattern matching),也称为 match-case 语句。这是 Python 3.10 最重要的新特性;该功能让你能够更轻松地控制程序流程——当满足特定条件(或“情况”)时,执行相应的代码块。

在本文中,我们将全面介绍 Python 中的 match-case 语句,帮助你实现对程序执行流程的精细控制。


关于 Python 版本的说明

在开始之前,我们先谈谈 Python 版本和基础知识。

如果你当前使用的是旧版本的 Python,我们建议你升级到 Python 3.10,以便充分利用本文内容。这样你就可以直接运行文中的代码片段,并根据自己的项目需求进行修改。

你可以访问 Python 官方下载页面 获取最新版本。如果你想深入了解 match-case 语句,可以查阅三个新的 Python 增强提案(PEPs)

  • PEP 636:模式匹配的入门教程(推荐起点)
  • PEP 634:详细规范说明
  • PEP 635:该特性的设计动机与原理

好了,现在让我们深入探讨 Python 的 match-case 语句。


Python 中的 match-case 语句

match-case 语句的基本用法看起来很像 Python 中的 if 语句。

对于熟悉 Java 或 C 等其他语言的开发者来说,match-case 可能类似于 switch 语句。switch 语句在功能上与 if-else 类似,但在定义多个分支时代码更简洁。

而 Python 的 match-case 语句更加强大,支持复杂的模式匹配。我们先看一个基本示例来了解其语法:

>>> command = 'Hello, World!'
>>> match command:
...     case 'Hello, World!':
...         print('Hello to you too!')
...     case 'Goodbye, World!':
...         print('See you later')
...     case other:
...         print('No match found')
...
Hello to you too!

这里我们定义了一个变量 command,并使用 match 关键字将其与后续每个 case 定义的模式进行匹配。

小提示matchcase 是所谓的“软关键字”(soft keywords),仅在 match-case 语句中具有特殊含义。你仍然可以在程序其他地方将它们用作普通变量名。

最后的 case other 相当于 if-elif-else 中的 else,也可以简写为 case _(下划线 _ 是通配符,表示“任意值”)。

上面的例子中我们使用了 print() 函数输出文本,但实际上任何命令或函数调用都可以放在 case 块中执行。下面我们会看到更复杂的例子。


为什么要使用 match-case 语句?

上面的例子完全可以用 if-elif-else 实现。但在本节中,我们将通过两个更复杂的例子展示 match-case 如何简化流程控制,使代码更清晰、更不易出错。

假设我们要编写一个脚本来处理大量文件,可以这样写:

>>> def file_handler_v1(command):
...     match command.split():
...         case ['show']:
...             print('List all files and directories: ')
...             # 列出文件和目录的代码
...         case ['remove', *files]:
...             print('Removing files: {}'.format(files))
...             # 删除文件的代码
...         case _:
...             print('Command not recognized')

输入仍然是一个字符串,通过 command.split() 按空格分割成字符串列表。

  • 第一个 case 在输入为 'show' 时匹配(split() 返回 ['show']),然后执行列出文件的逻辑(此处用注释代替实际代码,实际可使用 os 模块实现)。
  • 第二个 case 更有趣。例如:
>>> file_handler_v1('remove file1.txt file2.jpg file3.pdf')
Removing files: ['file1.txt', 'file2.jpg', 'file3.pdf']

这里 'remove' 被匹配,而 *files 是一个星号表达式(类似 *args),它会捕获后面任意数量的参数,并将它们存入 files 列表中。如果用 if-elif-else 实现相同逻辑,代码会更冗长且可读性较差。


更高级的用法:使用 |(或)和守卫条件(guard)

接下来,我们引入 或操作符 |case 内部的 if 条件(称为“守卫”)

>>> def file_handler_v2(command):
...     match command.split():
...         case ['show']:
...             print('List all files and directories: ')
...             # 列出文件
...         case ['remove' | 'delete', *files] if '--ask' in files:
...             del_files = [f for f in files if len(f.split('.')) > 1]
...             print('Please confirm: Removing files: {}'.format(del_files))
...             # 获取用户确认后删除文件
...         case ['remove' | 'delete', *files]:
...             print('Removing files: {}'.format(files))
...             # 直接删除文件
...         case _:
...             print('Command not recognized')
  • 第二和第三个 case 都能匹配 'remove''delete'
  • 第二个 case 还包含一个守卫条件 if '--ask' in files,只有当输入中包含 --ask 标志时才会触发。
  • 我们还用列表推导式过滤出带扩展名的文件(即 len(f.split('.')) > 1),这是一种简洁的 for 循环写法。
  • 第三个 case 则在没有 --ask 标志时匹配。

运行示例:

>>> file_handler_v2('remove --ask file1.txt file2.jpg file3.pdf')
Please confirm: Removing files: ['file1.txt', 'file2.jpg', 'file3.pdf']

>>> file_handler_v2('delete file1.txt file2.jpg file3.pdf')
Removing files: ['file1.txt', 'file2.jpg', 'file3.pdf']

关于 match-case 语句的最后思考

在本文中,我们介绍了 Python 的结构化模式匹配(match-case 语句),展示了它相比 if-elif-else 在代码量和可读性上的优势。

match-case 的能力远不止于此——你还可以传入对象(而非字符串),并对对象的属性进行模式匹配,非常强大!

重要提醒:对于像上面最后一个例子这样的复杂匹配,case 的顺序会直接影响程序行为。这与 if-elif-else 中的条件顺序类似。
举个例子:如果把第二和第三 case 的位置互换,--ask 标志将永远不会被匹配到!因此,在编写 case 时务必仔细考虑顺序。

严格来说,match-case 并没有为 Python 增加全新的功能,但它极大地简化了复杂的控制逻辑。建议你将本文所学应用到自己的项目中,尝试将一些现有的 if-elif-else 语句重写为 match-case 形式,亲身体验它的优势。

祝你编码愉快!