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

作者:Serdar Yegulalp

更多技术干货请关注公众号“云原生数据库

squids.cn,目前可体验全网zui低价RDS,免费的迁移工具DBMotion、SQL开发工具等。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/31390.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp-----封装接口

系列文章目录 uniapp-----封装接口 uniapp-----分包 文章目录 系列文章目录 uniapp-----封装接口 uniapp-----分包 文章目录 前言 一、技术 二、封装步骤 1.准备 ​编辑 2.代码填充 request.js: api.js: min.js 页面使用 总结 前言 uni…

mysql索引的数据结构(Innodb)

首选要注意,这里的数据结构是存储在硬盘上的数据结构,不是内存中的数据结构,要重点考虑io次数. 一.不适合的数据结构: 1.Hash:不适合进行范围查询和模糊匹配查询.(有些数据库索引会使用Hash,但是只能精准匹配) 2.红黑树:可以范围查询和模糊匹配,但是和硬盘io次数比较多. 二…

vue : 无法加载文件 C:\Users\…\npm\vue.ps1,因为在此系统上禁止运行脚本。

在 PowerShell 中创建 vue 项目时,出现了以下错误导致创建失败:vue : 无法加载文件 C:\Users\…\npm\vue.ps1,因为在此系统上禁止运行脚本。 报错原因 用户权限不足导致无法加载文件,以管理员身份运行终端或者 PowerShell 也可…

Go异常处理机制panic和recover

recover 使用panic抛出异常后, 将立即停止当前函数的执行并运行所有被defer的函数,然后将panic抛向上一层,直至程序crash。但是也可以使用被defer的recover函数来捕获异常阻止程序的崩溃,recover只有被defer后才是有意义的。 func main() { p…

Maven安装与配置

目录 一、Maven简介1.1 概述1.2 作用1.3 仓库 二、安装三、配置3.1 配置环境变量3.2 环境变量测试3.3 配置仓库 一、Maven简介 1.1 概述 Maven是一个开源的项目管理工具,用于构建和管理Java项目,基于项目对象模型(POM)的概念。它…

面试八股文Mysql:(1)事务实现的原理

1. 什么是事务 事务就是一组数据库操作,这些操作是一个atomic(原子性的操作) ,不可分割,要么都执行,要么回滚(rollback)都不执行。这样就避免了某个操作成功某个操作失败&#xff0…

CSS的使用

一、隐藏 1、文本隐藏 /*文本隐藏*/ .text-hidden{white-space: nowrap;overflow: hidden;text-overflow: ellipsis; } /*文本隐藏&#xff0c;悬浮显示*/ .text-hidden:hover{width: auto!important; }二、浮动样式 1、显示、隐藏浮动div <!DOCTYPE html> <html …

C++学习笔记总结练习:动态内存

动态内存 存在的问题&#xff1a;栈空间和堆空间的分配也是运行时内存分配&#xff0c;即动态内存分配。文字常量区、全局变量和静态变量区是在编译时内存分配&#xff0c;即静态内存分配。 栈空间的动态内存分配由操作系统管理。堆空间的动态内存分配由用户自身管理。二者可以…

putty使用记录

在官网下载并安装putty 一、SSH 二、FTP open 192.168.1.118 put -r C:\Users\Administrator\Desktop\test /opt/lanren312/test # 上传&#xff08;文件夹&#xff09; get -r /opt/lanren312/test C:\Users\Administrator\Desktop\test2 # 下载&#xff08;文件夹&#xff…

gray_dilation_rect

灰度图膨胀。图像的宽度和高度不变。 下面创建一个3*3的灰度图&#xff0c;左上角为1&#xff0c;右下角为3&#xff0c;其它为0。 byte[] barr new byte[9]; barr[0] 1; barr[8] 3; var img WHCSHalCon.Base.CreateByteImage(barr,…

Android Studio实现图形验证码

源代码 源代码MainActivity 效果图32行需要修改&#xff0c;不修改会报错&#xff1a;需要常量表达式&#xff0c;我的代码已修改 点击后 MainActivity import static com.example.graphicverificationcode.RxCaptcha.TYPE.NUMBER;import android.annotation.SuppressLint; …

获取 Android 的 SHA1 值

1、调试版&#xff0c;可以直接在 Android studio 中的 gradle 中查看。也可以用下面方法进行 前提要先确定签名文件所在的路径&#xff1a;调试版默认使用的签名文件是debug.keystore&#xff0c;文件处于 C 盘用户目录下的.android文件夹下。打开命令行工具&#xff0c; 1、…

Uniapp使用腾讯地图并进行标点创建和设置保姆教程

使用Uniapp内置地图 首先我们需要创建一个uniapp项目 首先我们需要创建一个uniapp项目 我们在HBuilder左上角点击文件新建创建一个项目 然后下面这张图的话就是uniapp创建项目过程当中需要注意的一些点和具体的操作 然后我们创建完项目之后进入到项目pages文件夹下&#xff…

Android 13 Launcher界面——移除Launcher的删除和卸载功能

目录 一.背景 二.将卸载功能进行屏蔽 三.将移除功能屏蔽 四.将Remove按钮与Uninstall按钮屏蔽

web-csrf

目录 CSRF与XSS的区别&#xff1a; get请求 原理&#xff1a; pikachu为例 post请求 pikachu为例 CSRF与XSS的区别&#xff1a; CSRF是借用户的权限完成攻击&#xff0c;攻击者并没有拿到用户的权限&#xff0c;而XSS是直接盗取到了用户的权限 get请求 原理&#xff1a;…

新法!《个人信息保护合规审计管理办法(征求意见稿)》解读

8月3日&#xff0c;依据《中华人民共和国个人信息保护法》等法律法规&#xff0c;国家互联网信息办公室起草了《个人信息保护合规审计管理办法&#xff08;征求意见稿&#xff09;》&#xff08;下文简称“办法”&#xff09;&#xff0c;并向社会公开征求意见。 据悉&#xff…

交互流程图设计软件都有哪些?

交互流程图是设计行业信息流、观点流或组件流的图形代表。但是市场上应该如何选择各种交互流程图软件呢&#xff1f;如何使用高质量的交互流程图软件来绘制高端氛围的高档流程图&#xff1f;今天&#xff0c;小边给您带来了十个超级实用的交互流程图软件&#xff0c;我希望能帮…

HCIA 路由器工作原理 及其 静态路由配置

目录 1、路由器工作原理 2、获取未知网段的方法&#xff1a; 3、静态路由 1&#xff09;写法&#xff1a; 2&#xff09;扩展配置 a、环回接口 配置命令&#xff1a; 环回接口的作用&#xff1a; b、手工汇总 手工汇总作用&#xff1a; c、路由黑洞 d、缺省路由 配置…

竞赛项目 疫情数据分析与3D可视化 - python 大数据

文章目录 0 前言1 课题背景2 实现效果3 设计原理4 部分代码5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 大数据全国疫情数据分析与3D可视化 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff0…

【位操作符的几种题型】

位操作符的几种题型 目录 题型一&#xff1a;寻找“单身狗”。 题型二&#xff1a;计算一个数在二进制中1的个数 题型三&#xff1a;不允许创建临时变量&#xff0c;交换两个整数的内容 题型一&#xff1a;寻找“单身狗”。 1.1题目解析 在一个整型数组中&#xff0c;只有…