首页 > 编程语言 >python 的 match case 用法详解

python 的 match case 用法详解

时间:2023-02-17 20:55:25浏览次数:40  
标签:case 匹配 Point python 模式 print match

Python 3.10 实现的 match 功能是其他开发语言中传统的 switch 的超集,它不仅仅是 switch,可以实现更为复杂的功能。模式匹配大大增加了控制流的清晰度和表达能力。

背景
虽然使用嵌套的“if”语句的“命令性”系列指令可以被用来完成类似结构化模式匹配的效果,但它没有“声明性”方式那样清晰。相反地,“声明性”方式指定了一个匹配所要满足的条件,并且通过其显式的模式使之更为易读。更强大的模式匹配例子可以在 Scala 和 Elixir 等语言中找到。 这种结构化模式匹配方式是“声明性”的并且会显式地为所要匹配的数据指定条件(模式)。

一直以来,Python 没有其他语言的 switch 方法来实现多条件分支,要求支持的呼声很高,Python 3.10.0 支持了它,而且是超级版的,实现的思路与它们大有不同。match 与 case 配合,由 case 从上到下将目标与语句中的每个模式进行比较,直到确认匹配,执行相应的模式下的语句。如果未确认完全匹配,则最终用通配符 _(如提供)将用作匹配情况。如所有的都不匹配且没有通配符,则相当于空操作。

模式由序列、映射、基本数据类型以及类实例构成。 模式匹配使得程序能够从复杂的数据类型中提取信息、根据数据结构实现分支,并基于不同的数据形式应用特定的动作。

语法
采用模式加上相应动作的 match 语句 和 case 语句 的形式的结构化模式匹配。 其中 match 与 case 在特点句法下为 Python 的软关键字(Soft keywords):

match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
match 语句接受一个表达式并将其值与以一个或多个 case 语句块形式给出的一系列模式进行比较。 具体来说,模式匹配的操作如下:

给定具有特定类型和结构的数据 (subject)
针对 subject 在 match 语句中求值
从上到下对 subject 与 case 语句中的每个模式进行比较:
直到确认匹配到一个模式,执行与被确认匹配的模式相关联的动作
如果没有确认到一个完全的匹配:
如果提供了使用通配符 _ 的最后一个 case 语句,则它将被用作已匹配模式
不存在使用通配符的 case 语句,则整个 match 代码块不执行任何操作
详细语法:

match_stmt: "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT
subject_expr:
| star_named_expression ',' star_named_expressions?
| named_expression
case_block: "case" patterns [guard] ':' block
guard: 'if' named_expression
注意,对 subject 的匹配不仅为具体值,还可以包括它的数据结构,可以匹配到全部结构和部分结构内容,并将这些匹配到的结构内容引用到关联的处理动作中作为变量。具体的理解可以看看下方的用法示例。另外:

匹配的不能是一个表达式,一定要是一个字面值或者结构
类似于解包赋值功能
元组和列表模式具有完全相同的含义,而且实际上能匹配任意序列
目标必须为一个序列
例外:模式不能匹配迭代器
序列模式不能匹配字符串(为了避免一个常见的错误)
支持通配符: [x, y, *rest] 和 (x, y, *rest) 的作用类似于解包赋值中的通配符
在 * 之后的名称也可以为_,因此 (x, y, *) 可以匹配包含两个条目的序列而不必绑定其余的条目
映射模式,如 {"bandwidth": b, "latency": l} 会从一个字典中捕获 "bandwidth" 和 "latency" 值,与序列模式不同,额外的键会被忽略。 也支持通配符 **rest。(但 **
是冗余的,因而不被允许)
用法
结构化模式匹配可以采取将一个变量与一个 case 语句中的字面值进行比较的最简单形式来使用,但 Python 的模式匹配真正针对的目标类型和形状的处理操作。接下来就用一些例子来说明:

匹配一个字面值
这是最简单的应用,一个值,即主词,被匹配到几个字面值,即模式。在下面的例子中,status 是匹配语句的主词。模式是每个 case 语句,字面值代表请求状态代码。匹配后,将执行与该 case 相关的动作:
grade = 3
match grade:
case 1:
print('一年级')
case 2:
print('二年级')
case 3:
print('三年级')
case _:
print('未知年级')

三年级

变量名 _ 作为 通配符 并确保目标将总是被匹配,是可选的,如果没有又之前 case 未得到匹配,则会执行一个空操作(no-op)。还可以用 | (表示或者)在一个模式中组合几个字面值:

grade = 5
match grade:
case 1:
print('一年级')
case 2:
print('二年级')
case 3:
print('三年级')
case 4 | 5 | 6:
print('高年级')
case _:
print('未知年级')

高年级

下边是一利用一个类状态实现的开关功能:

class switch:
on = 1
off = 0

status = 0

match status:
case switch.on :
print('Switch is on')
case switch.off :
print('Switch is off')
守卫 Guard
可以在 case 中编写 if 条件语句,实现与 if 语句类似的功能:

score = 81
match score:
case 100:
print('满分!')
case score if score >= 80:
print(f'高分啊~ {score}')
case score if score >= 60:
print('及格万岁!')
case _:
print('不知道说什么。')

高分啊~ 81

在 case 后面可以加入一个 if 判断作为守卫,如匹成功但守卫为假,则继续尝试下一个 case 案例块,值捕获发生在评估守卫之前。再来一个例子:

def fun(score):
match score:
case 100:
print('满分!')
case score if score >= 80:
print(f'高分啊~ {score}')
case score if score >= 60:
print('及格万岁!')
case score if score in [57, 58, 59]:
print('这成绩也是没谁了 ··!')
case _:
print('不知道说什么。')

fun(59)

这成绩也是没谁了 ··!

带有字面值和变量的模式
模式可以看起来像解包形式,而且模式可以用来绑定变量。在这个例子中,一个数据点可以被解包为它的 x 坐标和 y 坐标:

point is an (x, y) tuple

match point:
case (0, 0):
print("坐标原点")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("未法的坐标数据")
第一个模式有两个字面值 (0, 0) ,可以看作是上面所示字面值模式的扩展。接下来的两个模式结合了一个字面值和一个变量,而变量 绑定 了一个来自主词的值(point)。 第四种模式捕获了两个值,这使得它在概念上类似于解包赋值 (x, y) = point 。

这种情况也可以增加守卫:

point = (60, 0)

match point:
case (0, 0):
print("坐标原点")
case (0, y):
print(f"Y={y}")
case (x, 0) if x > 50:
print(f"X={x},点在 x 轴的远处")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("未法的坐标数据")

X=60,点在 x 轴的远处

命名的常量
模式可以使用命名的常量,且必须使用 . 以防止被解释为捕获变量:

from enum import Enum
class Color(Enum):
RED = 0
GREEN = 1
BLUE = 2

match color:
case Color.RED:
print("I see red!")
case Color.GREEN:
print("Grass is green")
case Color.BLUE:
print("I'm feeling the blues

标签:case,匹配,Point,python,模式,print,match
From: https://www.cnblogs.com/mrsphere/p/17131482.html

相关文章

  • python的下载安装与使用
    一、python解释器版本创作者:龟叔1.1python1.X(可忽略)1.2python2.xpython2.x的最高版本是2.7版本,现在仍然有不少企业老项目在使用2.7版本1.3python3.x目前比较稳定的版......
  • Python有以下几个方面的优势
    Python是一种非常流行和强大的编程语言,它有以下几个方面的优势:1、易学习,易阅读:Python语法简洁清晰,代码风格优雅,类似于英语。Python适合编程初学者入门,也适合经验丰富的开发......
  • Python3默认字符编码的问题
    输出报错UnicodeEncodeError:'ascii'codeccan'tencodecharactersinposition0-1:ordinalnotinrange(128)>>>importsys>>>sys.stdout.encoding'ANSI_X3.4-1......
  • MySql语句中,select和update使用case when then end笔记
    在日常项目中,mysql的casewhenthenend还是比较有意思的,请看例子:select的使用数据表结构:执行语句:SELECTcount(*),CASEWHENrole_countbetween1and100TH......
  • 通过Windows定时任务执行Python脚本给钉钉群发送消息
    前提:已经存在有成功发送钉钉群机器人消息的python脚本,参考上一篇Python调用钉钉群机器人发送群消息Windows定时任务设置1、本机是Win7系统:控制面板->系统和安全->管理工......
  • python入门之函数function
    """函数function定义:功能,使用一个名称,包装多个语句语法:做def名字(形参):函数体......
  • Python中的几种矩阵乘法【转】
    一. np.dot()1.同线性代数中矩阵乘法的定义。np.dot(A,B)表示:对二维矩阵,计算真正意义上的矩阵乘积。对于一维矩阵,计算两者的内积。2.代码 【code】importnum......
  • Appium+python之APP自动化五(卸载app)
    一、python中adb命令卸载app卸载app的adb命令使用adbuninstall,需要先确认安装app的包名,在此处定义了查询第三方安装app的方法和删除app的方法,在删除时传入的app包名先判......
  • python将列表切割成小列表
    想实现类似于php中array_chunk()函数把一个数组分割为新的数组块。python没有相关的函数,那么分享一下处理方法:如:有一个列表l,元素是a到z的字符串,我想将他切成3个字母为......
  • python72前端框架之vue 组件间父子通信,ref属性,动态组件,插槽,计算属性,监听属性,node环境
    组件其他跟组件和组件一些问题newVue()--->管理div----》根组件自己再定义的全局,局部是组件组件有自己的html,css,js---》数据,事件。。。。。在......