IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python:初识v3.10结构化模式匹配 -> 正文阅读

[Python知识库]python:初识v3.10结构化模式匹配

python3.10增加了采用模式加上相应动作的 match 语句 和 case 语句 的形式的结构化模式匹配。 模式由序列、映射、基本数据类型以及类实例构成。 模式匹配使得程序能够从复杂的数据类型中提取信息、根据数据结构实现分支,并基于不同的数据形式应用特定的动作。

语法与操作

?模式匹配的通用语法如下:

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 代码块不执行任何操作。

简单模式:匹配一个字面值

让我们把这个例子看作是模式匹配的最简单形式:一个值,即主词,被匹配到几个字面值,即模式。在下面的例子中,status 是匹配语句的主词。模式是每个 case 语句,字面值代表请求状态代码。匹配后,将执行与该 case 相关的动作:

def http_error(status):
    match status:
        case 400:
            return "请求错误!"
        case 404:
            return "页面不存在!"
        case 418:
            return "yyds!"
        case _:
            return "网络有点问题!"


if __name__ == '__main__':
    print(http_error(500))

运行结果

网络有点问题!

Process finished with exit code 0

如果传给上述函数的?status?为?418,则会返回?"yyds!"。 如果传给上述函数的?status?为?500,则带有_的?case?语句将作为通配符匹配,并会返回?"网络有点问题!"。?请注意最后一个代码块:变量名_将作为 通配符 并确保目标将总是被匹配。_的使用是可选的。

?你可以使用?| (“ or ”)在一个模式中组合几个字面值:

def http_error(status):
  match status:
      case 400 | 404 | 403:
          return "请求错误!"
      case _:
          return "网络有点问题!"


if?name?== 'main': print(http_error(500))

运行结果
```python
网络有点问题!

Process finished with exit code 0

?无通配符的行为

如果我们修改上面的例子,去掉最后一个case块,这个例子就变成:

def http_error(status):
    match status:
        case 400 | 404 | 403:
            return "请求错误!"


if __name__ == '__main__':
    print(http_error(200))

运行结果

None

Process finished with exit code 0

如果不在case语句中使用?_,可能会出现不存在匹配的情况。如果不存在匹配,则行为是一个无操作行为。例如,如果传入了值为200的?status?,就会直接返回函数的默认值None

带有字面值和变量的模式

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

# point 是一个 (x, y) 元组
match point:
    case (0, 0):
        print("Origin")
    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("Not a point")

第一个模式有两个字面值(0, 0),可以看作是上面所示字面值模式的扩展。接下来的两个模式结合了一个字面值和一个变量,而变量 绑定 了一个来自主词的值(point)。 第四种模式捕获了两个值,这使得它在概念上类似于解包赋值(x, y) = point

?一个简单的例子:

point = (60, 60)
match point:
    case (0, 0):
        print("坐标原点")
    case (0, y):
        print(f"Y={y}")
    case _:
        raise ValueError("Not a point")

运行结果

Traceback (most recent call last):
  File "E:\git_dfwsgroup\9first\xzProjectTeamApi\lms3_9first_com\apiInterface\web\classify.py", line 16, in <module>
    raise ValueError("Not a point")
ValueError: Not a point

Process finished with exit code 1

模式和类

如果你使用类来结构化你的数据,你可以使用类的名字,后面跟一个类似构造函数的参数列表,作为一种模式。这种模式可以将类的属性捕捉到变量中:

class Point:
    x: int
    y: int

def location(point):
    match point:
        case Point(x=0, y=0):
            print("Origin is the point's location.")
        case Point(x=0, y=y):
            print(f"Y={y} and the point is on the y-axis.")
        case Point(x=x, y=0):
            print(f"X={x} and the point is on the x-axis.")
        case Point():
            print("The point is located somewhere else on the plane.")
        case _:
            print("Not a point")

?一个简单的例子:

class Point:
    x: int
    y: int


def location(point):
    match point:
        case Point(x=0, y=0):
            print("原点是点的位置。")
        case Point(x=0, y=y):
            print(f"Y={y} 这个点在y轴上。")
        case Point(x=x, y=0):
            print(f"X={x} 这个点在x轴上。")
        case Point():
            print("这个点位于平面上的其他地方。")
        case _:
            print("不是一个点")


p = Point()
p.x = 0
p.y = 0
location((p.x, p.y))

运行结果

不是一个点

Process finished with exit code 0

?上述代码中就是把类中的属性值进行判断,当然,如果使用构造方法就会减少对象调用属性的操作:

class Point:
    def __init__(self, x, y):
        self.x: int = x
        self.y: int = y


def location(point):
    match point:
        case Point(x=0, y=0):
            print("原点是点的位置。")
        case Point(x=0, y=y):
            print(f"Y={y} 这个点在y轴上。")
        case Point(x=x, y=0):
            print(f"X={x} 这个点在x轴上。")
        case Point():
            print("这个点位于平面上的其他地方。")
        case _:
            print("不是一个点")


location(Point(0, 1))

运行结果

Y=1 这个点在y轴上。

Process finished with exit code 0

?您也可以使用官方提供的装饰器操作:

from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int


def location(point):
    match point:
        case Point(x=0, y=0):
            print("原点是点的位置。")
        case Point(x=0, y=y):
            print(f"Y={y} 这个点在y轴上。")
        case Point(x=x, y=0):
            print(f"X={x} 这个点在x轴上。")
        case Point():
            print("这个点位于平面上的其他地方。")
        case _:
            print("不是一个点")


location(Point(0, 1))

运行结果

Y=1 这个点在y轴上。

Process finished with exit code 0

这个装饰器的作用,就是把没有构造方法(__init__)的类,添加了一个构造方法。

嵌套模式

模式可以任意地嵌套。 例如,如果我们的数据是由点组成的短列表,则它可以这样被匹配:

match points:
    case []:
        print("No points in the list.")
    case [Point(0, 0)]:
        print("The origin is the only point in the list.")
    case [Point(x, y)]:
        print(f"A single point {x}, {y} is in the list.")
    case [Point(0, y1), Point(0, y2)]:
        print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
    case _:
        print("Something else is found in the list.")

?一个简单的例子:

from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int


def location(point):
    match point:
        case []:
            print("列表上没有点。")
        case [Point(0, 0)]:
            print("原点是列表中唯一的点。")
        case [Point(x, y)]:
            print(f"单点{x}, {y}在列表中。")
        case [Point(0, y1), Point(0, y2)]:
            print(f"Y轴上{y1}、{y2}处的两点在列表中。")
        case _:
            print("在列表中找到了其他东西。")


location([Point(0, 2), Point(0, 1)])

运行结果

Y轴上2、1处的两点在列表中。

Process finished with exit code 0

复杂模式和通配符

到目前为止,这些例子仅在最后一个case语句中使用了?_。 但通配符可以被用在更复杂的模式中,例如?('error', code, _)。 举例来说:

match test_variable:
    case ('warning', code, 40):
        print("A warning has been received.")
    case ('error', code, _):
        print(f"An error {code} occurred.")

?一个简单的例子:

def location(point):
    match point:
        case ('warning', code, 500):
            print(f"收到了一个警告 {code}。")
        case ('error', code, _):
            print(f"发生错误 {code}。")


location(("error", 900, "_"))

运行结果

发生错误 900。

Process finished with exit code 0

守护项

我们可以向一个模式添加if子句,称为“守护项”。 如果守护项为假值,则match将继续尝试下一个?case?语句块。 请注意值的捕获发生在守护项被求值之前:

match point:
    case Point(x, y) if x == y:
        print(f"The point is located on the diagonal Y=X at {x}.")
    case Point(x, y):
        print(f"Point is not on the diagonal.")

?一个简单的例子:

from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int


def location(point):
    match point:
        case Point(x, y) if x == y:
            print(f"点位于对角线上的Y=X {x}处。")
        case Point(x, y):
            print("点不在对角线上。")


location(Point(1, 1))

运行结果

点位于对角线上的Y=X 1处。

Process finished with exit code 0


以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的点赞和分享哟,谢谢!

未完,待续…

一直都在努力,希望您也是!

微信搜索公众号:就用python

文章作者:李 锋|编辑排版:梁莉莉

更多内容欢迎关注公众号

?

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-12-08 13:46:09  更:2021-12-08 13:47:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 5:46:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码