迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Python >

Python 中的结构模式匹配

作者:迹忆客 最近更新:2023/06/14 浏览次数:

在 Python 3.10 之前,我们没有任何内置的方式来使用结构模式匹配,在其他编程语言中称为 switch-case。 从 Python 3.10 版本开始,我们不能使用 match ... case 语句来模拟 switch ... case 语句。

本篇文章介绍结构模式匹配及其在 Python 中的重要性。 它还使用不同的模式来演示如何使用 match ... case 语句。


结构模式匹配简介及其重要性

截至 2021 年初,我们无法在低于或等于 3.9 的已发布 Python 版本中使用 match 关键字。 那时,我们习惯于使用字典或嵌套的 if/elif/else 语句来模拟 switch ... case

但是,Python 3.10 引入了一个新特性,称为结构模式匹配(match ... case 语句)。 它相当于我们在 Java、C++ 和许多其他编程语言中使用的 switch ... case 语句。

这一新功能使我们能够编写简单、易于阅读且最不容易出错的流程控制语句。


在 Python 中使用结构模式匹配

结构模式匹配用作 switch ... case 语句,比这更强大。 如何? 让我们探索下面的一些示例,以了解它们在不同情况下的用途。

match ... case 语句的基本使用

示例代码:

colour = "blue"
match colour:
    case "green":
        print("The specified colour is green")
    case "white":
        print("Wow, you've picked white")
    case "green":
        print("Great, you are going with green colour")
    case "blue":
        print("Blue like sky...")

输出:

Blue like sky...

在这里,我们首先有一个包含蓝色的可变颜色。 然后,我们使用 match 关键字,它将颜色变量的值与各种指定的案例进行匹配,其中每个案例都以 case 关键字开头,后跟我们要比较或检查的模式。

模式可以是以下之一:

  • 文本模式
  • 捕获模式
  • 通配符模式
  • 定值模式
  • 序列模式
  • 映射模式
  • 类模式
  • 或模式
  • walrus 模式

match ... case 语句只运行第一个匹配的 case 下的代码。

如果没有匹配到 case 怎么办? 用户将如何知道它? 为此,我们可以有一个默认情况,如下所示。

示例代码:

colour = "yellow"
match colour:
    case "green":
        print("The specified colour is green")
    case "white":
        print("Wow, you've picked white")
    case "green":
        print("Great, you are going with green colour")
    case "blue":
        print("Blue like sky...")
    case other:
        print("No match found!")

输出:

No match found!

使用 match ... case 来检测和解构数据结构

示例代码:

student = {
     "name": {"first": "Mehvish", "last": "Ashiq"},
     "section": "B"
}

match student:
    case {"name": {"first": firstname}}:
        print(firstname)

输出:

Mehvish

在上面的示例中,结构模式匹配在以下两行代码中起作用:

match student:
    case {"name": {"first": firstname}}:

我们使用 match ... case 语句通过从学生数据结构中提取学生的名字来找到它。 在这里,student 是一个包含学生信息的字典。

案例行指定我们的模式来匹配学生。 考虑到上面的例子,我们寻找一个带有“name”键的字典,其值为一个新字典。

这个嵌套字典包含一个“first”键,其值绑定到 firstname 变量。 最后,我们使用 firstname 变量来打印值。

如果您更深入地观察它,我们已经了解了这里的映射模式。 如何? 映射模式看起来像 {"student": s, "emails": [*es]},它匹配映射与至少一组指定的键。

如果所有子模式都匹配它们对应的值,那么它将在与键对应的值匹配期间绑定任何子模式绑定。 如果我们想要允许捕获额外的项目,我们可以在模式的末尾添加 **rest。

使用 match ... case 与捕获模式和序列模式

示例代码:

def sum_list_of_numbers(numbers):
    match numbers:
        case []:
            return 0
        case [first, *rest]:
            return first + sum_list_of_numbers(rest)

sum_list_of_numbers([1,2,3,4])

输出:

10

这里,我们使用递归函数,使用捕获模式捕获到指定模式的匹配,并绑定到名字上。

在此代码示例中,如果第一种情况与空列表匹配,则第一种情况返回 0 作为总和。 第二种情况使用带有两个捕获模式的序列模式来匹配列表与多个项目/元素之一。

在这里,列表中的第一项被捕获并绑定到名字,而第二个捕获模式 *rest 使用解包语法来匹配任意数量的项目/元素。

请注意 ,其余部分绑定到包含数字的所有项目/元素的列表,不包括第一个。 为了获得输出,我们通过传递上面给出的数字列表来调用 sum_list_of_numbers() 函数。

使用 match ... case 和通配符模式

示例代码:

def sum_list_of_numbers(numbers):
    match numbers:
        case []:
            return 0
        case [first, *rest]:
            return first + sum_list_of_numbers(rest)
        case _:
            incorrect_type = numbers.__class__.__name__
            raise ValueError(f"Incorrect Values. We Can only Add lists of numbers,not {incorrect_type!r}")

sum_list_of_numbers({'1':'2','3':'4'})

输出:

ValueError: Incorrect Values. We Can only Add lists of numbers, not 'dict'

我们在学习 match ... case 语句的基本用法时学习了使用通配符模式的概念,但没有在那里介绍通配符模式术语。 想象一下前两种情况不匹配的情况,我们需要一个 catchall 模式作为我们的最终情况。

例如,如果我们得到任何其他类型的数据结构而不是列表,我们希望引发错误。 在这里,我们可以使用 _ 作为通配符模式,它将匹配任何内容而不绑定到名称。 我们在最后一个案例中添加错误处理以通知用户。

你怎么说? 我们的模式适合搭配吗? 让我们通过传递字符串值列表来调用 sum_list_of_numbers() 函数来测试它,如下所示:

sum_list_of_numbers(['1','2','3','4'])

它将产生以下错误:

TypeError: can only concatenate str (not "int") to str

因此,我们可以说该模式仍然不够万无一失。 为什么? 因为我们将列表类型数据结构传递给 sum_list_of_numbers() 函数,但具有字符串类型值,而不是我们预期的 int 类型。

请参阅以下部分以了解如何解决它。

在类模式中使用 match ... case

示例代码:

def sum_list_of_numbers(numbers):
    match numbers:
        case []:
            return 0
        case [int(first), *rest]:
            return first + sum_list_of_numbers(rest)
        case _:
            raise ValueError(f"Incorrect values! We can only add lists of numbers")

sum_list_of_numbers(['1','2','3','4'])

输出:

ValueError: Incorrect values! We can only add lists of numbers

基本情况(第一种情况)返回 0; 因此,求和仅适用于我们可以用数字相加的类型。 请注意,Python 不知道如何添加文本字符串和数字。

所以,我们可以使用类模式来限制我们的模式只匹配整数。 类模式类似于映射模式,但匹配属性而不是键。

使用 match ... case 和 OR 模式

示例代码:

def sum_list_of_numbers(numbers):
    match numbers:
        case []:
            return 0
        case [int(first) | float(first), *rest]:
            return first + sum_list_of_numbers(rest)
        case _:
            raise ValueError(f"Incorrect values! We can only add lists of numbers")

假设我们想让 sum_list_of_numbers() 函数用于值列表,无论是 int 类型还是 float 类型的值。 我们使用用竖线符号 (|) 表示的 OR 模式。

如果指定列表包含 int 或 float 类型值以外的值,则上述代码必须引发 ValueError。 让我们考虑以下所有三种情况进行测试。

测试 1:传递具有 int 类型值的列表:

sum_list_of_numbers([1,2,3,4]) #output is 10

测试 2:传递具有 float 类型值的列表:

sum_list_of_numbers([1.0,2.0,3.0,4.0]) #output is 10.0

测试 3:传递具有除 intfloat 类型之外的任何其他类型的列表:

sum_list_of_numbers(['1','2','3','4'])
#output is ValueError: Incorrect values! We can only add lists of numbers

如您所见,由于使用了 OR 模式,sum_list_of_numbers() 函数适用于 int 和 float 类型的值。

将 match ... case 与文字模式一起使用

示例代码:

def say_hello(name):
    match name:
        case "Mehvish":
            print(f"Hi, {name}!")
        case _:
            print("Howdy, stranger!")
say_hello("Mehvish")

输出:

Hi, Mehvish!

此示例使用与文字对象匹配的文字模式,例如,显式数字或字符串,正如我们在学习 match ... case 语句的基本用法时所做的那样。

它是最基本的模式类型,让我们模拟一个类似于 Java、C++ 和其他编程语言的 switch ... case 语句。 您可以访问此页面以了解所有模式。

上一篇:在 Python 中取消设置 Linux 环境变量

下一篇:没有了

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 Python 中取消设置 Linux 环境变量

发布时间:2023/06/14 浏览次数:122 分类:Python

在本文中,我们将学习在 Python 中取消设置 Linux 环境变量的不同方法。 最有用的方法是使用 unset 命令。但是,我们可以使用其他几种方法在 Python 中取消设置 Linux 环境变量。 阅读文章以探索更

在 Python 脚本中设置环境变量

发布时间:2023/06/14 浏览次数:117 分类:Python

环境变量是与系统进程交互的一种深入方式; 它允许用户获得有关系统属性、路径和已经存在的变量的更详细信息。我们如何使用环境变量

Python 中的信号量

发布时间:2023/06/14 浏览次数:198 分类:Python

在本篇文章中,我们将学习如何使用信号量在 Python 中处理多线程。 如何同步访问线程和有限数量的资源?信号量 同步控制器是一个信号量。 信号量为线程提供对有限数量资源的同步访问。

在 Python 中使用 setLevel() 设置日志级别

发布时间:2023/06/14 浏览次数:82 分类:Python

Python 提供了一个单独的日志记录模块作为其标准库的一部分,以简化日志记录。 本文将讨论日志记录 setLevel 及其在 Python 中的工作方式。Python登录程序的功能

Python 日志记录传播

发布时间:2023/06/14 浏览次数:174 分类:Python

本文介绍了 LevelFilter 的使用,以显示如何将特定级别及更高级别(例如,INFO 及更高级别)的特定记录器名称的消息记录到特定的日志处理程序。Python 日志记录传播

Python 全局日志记录器

发布时间:2023/06/14 浏览次数:146 分类:Python

本文介绍 Python 中的日志记录模块。 它还介绍了日志记录级别及其重要性,从而生成了一个代码示例,演示了 Python 日志记录模块的全局使用。

在 Python 中可视化树

发布时间:2023/06/14 浏览次数:150 分类:Python

由于许多不同的原因,决策树是一种常见的监督学习技术。 决策树的优点包括我们可以将它们用于分类和回归,它们不需要特征缩放,而且决策树易于阅读。本文介绍了 Python 的 Graphviz 来显示

在 Python 中打印二叉树

发布时间:2023/06/14 浏览次数:101 分类:Python

本文将讨论二叉树以及我们如何使用它。 我们还将看到如何使用 Python 打印它。我们将了解在处理二叉树时使用的术语。 我们还将研究使用 Python 代码的二叉树示例。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便