浅析如何在Python中使用结构模式匹配

 更新时间:2023年08月11日 14:25:28   作者:Serdar Yegulalp  
在Python 3.10中引入了模式匹配语法,允许我们在应用程序中使用强大的新编程技术进行决策,下面我们就来讲讲如何在Python中使用结构模式匹配吧

在Python 3.10中引入的模式匹配语法允许在应用程序中使用强大的新编程技术进行决策。Python虽然功能强大且广受欢迎,但长期以来缺乏其他语言中的一种流程控制方式,即以一种优雅的方式将一个值与多个可能的条件进行匹配。在C和C++中,这是通过构造switch/case语句来实现的;在Rust中,这被称为“模式匹配”。

在Python中,传统的实现方式并不优雅。一种方式是编写一系列的表达式。另一种方式是将要匹配的值作为字典的键存储起来,然后使用这些值来执行相应的操作,例如将函数作为值存储,并使用键或其他变量作为输入。在许多情况下,这种方式可以很好地工作,但构建和维护起来可能会很麻烦,使用if/elif/else语句。

在经过多次失败的提案后,Python语言创始人Guido van Rossum和其他一些贡献者最近提出的一个提案已被接受,将在Python 3.10中引入结构化模式匹配。结构化模式匹配不仅可以执行简单的样式匹配,还支持更广泛的用例。

Python结构化模式匹配

结构化模式匹配引入了语句和模式语法到Python中。该语句遵循与if/elif/else相同的基本概述。它接受一个对象,对该对象进行一项或多项匹配模式的测试,并在找到匹配时执行相应的操作。

match command:
    case "quit":
        quit()
    case "reset":
        reset()
    case unknown_command:
        print (f"Unknown command '{unknown_command}'")

每个语句后面都跟着一个要匹配的模式。 在上面的示例中,我们使用简单的字符串作为我们的匹配目标,但更复杂的匹配也是可能的。事实上,结构化模式匹配的主要用例是匹配类型的模式,而不是值的模式。Python通过从上到下遍历案例列表来执行匹配。在第一个匹配时,Python执行相应块中的语句,然后跳到块的末尾并继续执行程序的其余部分。在案例之间没有“穿透”,但可以设计逻辑来处理单个块中的多个可能情况。(稍后会详细介绍)还可以捕获匹配的全部或部分内容并重新使用它。在上面的示例中,如果没有匹配成功,值将被“捕获”在变量中,以便我们可以重新使用它。

用Python结构模式匹配对变量进行匹配

这里有一个需要注意的事项。如果在语句中列出变量名,这并不意味着应该对命名变量的内容进行匹配。在case语句中,变量用于捕获正在匹配的值。如果想要匹配变量的内容,那么该变量必须以点分隔的名称表示,就像枚举一样。以下是一个示例:

from enum import Enum
class Command(Enum):
    QUIT = 0
    RESET = 1
​
match command:
    case Command.QUIT:
        quit()
    case Command.RESET:
        reset()

不必使用枚举;任何点分隔的属性名称都可以。但是枚举通常是在Python中执行此操作的最熟悉和惯用的方式。不能通过索引来匹配变量的内容。例如,x[0]将被拒绝作为语法错误。

使用Python结构化模式匹配进行多个元素的匹配

与模式匹配最有效的工作的关键不仅仅是将其用作字典查找或if/else链的替代品。它是描述要匹配的结构的方式。通过这种方式,可以根据要匹配的元素数量或它们的组合进行匹配。这里是一个稍微复杂一些的例子。在这个例子中,用户输入一个命令,可选择性地跟着一个文件名。

command = input("Command:")
match command.split():
    case ["quit"]:
        quit()
    case ["load", filename]:
        load_from(filename)
    case ["save", filename]:
        save_to(filename)
    case _:
        print (f"Command '{command}' not understood")

我们依次来看一下这些情况:

  • case ["quit"]:测试我们正在匹配的是否是只包含一个元素的列表,该元素是由输入进行拆分得到的字符串"quit"。
  • case ["load", filename]:测试第一个拆分元素是否是字符串"load",并且是否有一个紧随其后的字符串。如果是这样,我们将第二个字符串存储在变量filename中,并将其用于进一步的操作。
  • case ["save", filename]:与上述情况类似,测试第一个拆分元素是否是字符串"save",并且是否有一个紧随其后的字符串。如果是这样,我们将第二个字符串存储在变量filename中,并将其用于进一步的操作。
  • case _:这是一个通配符匹配。如果到目前为止没有进行其他匹配,它将匹配。请注意,下划线变量_实际上不绑定到任何内容;该名称用作命令的信号,表示该情况是一个通配符。(这就是为什么我们在块的主体中引用该变量;没有捕获到任何内容。)

在Python中结构模式的匹配模式

模式可以是简单的值,也可以包含更复杂的匹配逻辑。以下是一些示例:

case "a":匹配单个值"a"。 

case ["a","b"]:匹配集合["a","b"]。 

case ["a", value1]:匹配包含两个值的集合,并将第二个值放入捕获变量value1中。 

case ["a", *values]:匹配至少包含一个值的集合。其他值(如果有)将存储在values中。请注意,每个集合中只能包含一个星号项(就像在Python函数中的星号参数一样)。 

case ("a"|"b"|"c"):使用括号运算符()可以在单个块中处理多个情况。在这里,我们匹配"a""b""c"。 

case ("a"|"b"|"c") as letter:与上述情况类似,只是现在将匹配的项放入变量letter中。 

case ["a", value] if :仅当表达式为真时才匹配捕获。可以在表达式中使用捕获变量。例如,如果我们使用value in valid_values,则只有在捕获的值实际上在集合valid_values中时,才会匹配。 

case ["z", _]:以"z"开头的任何项集合都会匹配。

使用Python结构化模式匹配对对象进行匹配

Python结构化模式匹配系统最高级的功能是能够针对具有特定属性的对象进行匹配。考虑一个应用程序,我们正在处理一个名为data的对象,我们希望将其转换为文件并从函数中返回。

match media_object:
    case Image(codec="jpg"):
        # Return as-is
        return media_object
    case Image(codec="png") | Image(codec="gif"):
        return render_as(media_object, "jpg")
    case Video():
        raise ValueError("Can't extract frames from video yet")
    case other_type:
        raise Exception(f"Media object {media_object} 
            of type {codec} can't be handled yet")

在上述每种情况中,我们都在寻找特定类型的对象,有时还具有特定的属性。第一个情况匹配具有属性image_codec设置为"jpg"的对象。第二个情况匹配如果type"png""gif"。第三个情况匹配任何类型为Video的对象,无论其属性如何。最后一个情况是我们的通配情况,如果其他情况都不匹配,它将捕获所有对象,尽管我们使用了一个实际的名称来捕获它,而不是使用_。我们还可以在对象匹配中进行捕获:

match media_object:
    case Image(codec=media_type):
        print (f"Image of type {media_type}")

有效地使用Python结构模式匹配

Python结构化模式匹配的关键是编写能够覆盖所要匹配的结构情况的匹配。对常量进行简单的测试是可以的,但如果只是这样做,那么简单的字典查找可能是一个更好的选择。结构化模式匹配的真正价值在于能够根据对象的模式进行匹配,而不仅仅是一个特定的对象或一组对象的选择。另一个重要的事情是要记住匹配的顺序。你首先测试哪些匹配将对整体匹配的效率和准确性产生影响。大多数构建了长链的人会意识到这一点,但由于潜在的复杂性,模式匹配要求你更加仔细地思考顺序。将最具体的匹配放在最前面,将最一般的匹配放在最后。最后,如果你的问题可以用简单的链式结构或字典查找来解决,那么请使用它!模式匹配是强大的,但并不是万能的。在解决问题时,请根据问题的特点选择最合适的方法。

到此这篇关于浅析如何在Python中使用结构模式匹配的文章就介绍到这了,更多相关Python结构模式匹配内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python虚拟环境的安装配置图文教程

    python虚拟环境的安装配置图文教程

    下面小编就为大家带来一篇python虚拟环境的安装配置图文教程。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Python txt文件常用读写操作代码实例

    Python txt文件常用读写操作代码实例

    这篇文章主要介绍了Python txt文件常用读写操作代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Python利用PyPDF2库合并多个pdf文件

    Python利用PyPDF2库合并多个pdf文件

    PyPDF2库是一个用于处理PDF文件的Python库,它提供了一系列的工具来读取、编辑、合并、拆分和加密PDF文件,使得我们可以在Python环境下轻松地对PDF文件进行操作,本文将带大家介绍如何通过Python的PyPDF2库合并多个pdf文件,需要的朋友可以参考下
    2023-05-05
  • Selenium定位浏览器弹窗方法实例总结

    Selenium定位浏览器弹窗方法实例总结

    弹出框是自动化测试中一种常见的元素,这种元素通常是客户端自带的,下面这篇文章主要给大家介绍了关于Selenium定位浏览器弹窗方法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Python中pygame游戏模块的用法详解

    Python中pygame游戏模块的用法详解

    Pygame是一组用来开发游戏软件的 Python 程序模块,Pygame 在 SDL(Simple DirectMedia Layer) 的基础上开发而成,它提供了诸多操作模块,本文给大家介绍了Python中pygame游戏模块的用法,需要的朋友可以参考下
    2024-01-01
  • 详解Python中的三器一闭

    详解Python中的三器一闭

    这篇文章主要介绍了详解Python中的三器一闭,Python中的三器一闭是指迭代器、装饰器、生成器和闭包,需要的朋友可以参考下
    2023-05-05
  • Pandas提取含有指定字符串的行(完全匹配,部分匹配)

    Pandas提取含有指定字符串的行(完全匹配,部分匹配)

    本文主要介绍了Pandas提取含有指定字符串的行(完全匹配,部分匹配),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Python多进程multiprocessing.Pool类详解

    Python多进程multiprocessing.Pool类详解

    这篇文章主要为大家详细介绍了Python多进程multiprocessing.Pool类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • Python实现的批量修改文件后缀名操作示例

    Python实现的批量修改文件后缀名操作示例

    这篇文章主要介绍了Python实现的批量修改文件后缀名操作,涉及Python目录文件的遍历、重命名等相关操作技巧,需要的朋友可以参考下
    2018-12-12
  • Tensorflow获取张量Tensor的具体维数实例

    Tensorflow获取张量Tensor的具体维数实例

    今天小编就为大家分享一篇Tensorflow获取张量Tensor的具体维数实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01

最新评论