RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1337907
Accepted
Dmitry
Dmitry
Asked:2022-03-13 16:44:05 +0000 UTC2022-03-13 16:44:05 +0000 UTC 2022-03-13 16:44:05 +0000 UTC

Python 3.10 中的匹配案例构造

  • 772

2021 年 10 月 4 日,Python 3.10 发布。match-case在其他更新中,使用称为结构模式匹配的构造的能力或pattern matching

如何使用这个设计?

对于早期版本的 Python,请参阅此 ruSO 答案中的实现(类似于 switch-case 构造)。

python
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    GrAnd
    2022-03-13T19:04:16Z2022-03-13T19:04:16Z

    Python 3.10 引入了模式匹配

    本资料是文章《如何在 Python 中使用结构模式匹配》的翻译

    Python 3.10 的新版本引入case/match了负责在语言中实现模式匹配语法的运算符。

    尽管 Python 简单且受欢迎,但与其他语言不同,它没有单独的流控制形式——一种获取值并优雅地将其与许多可能条件之一匹配的方法。在 C 和 C++ 中,这个特性是由结构实现的switch/case,而在 Rust 中,它被称为模式匹配。

    到目前为止,除了使用构造if/elif/else和字典查找之外,在 Python 中还没有优雅的方法来做到这一点。这两种方法都有效,但由于它们的体积庞大,它们可能使代码更难阅读。

    多年来,已经多次尝试switch/case在 Python 中包含类型语法,但都失败了。这是结构模式匹配的第一个实现,目前仅在开发人员版本中可用。(请注意,从 version 开始,每个人都可以使用该实现python 3.10)

    Python中的模式匹配简介

    结构模式匹配引入了一个match/case与switch/case. 操作员根据一个或多个模式检查对象,如果找到匹配项,则执行操作。

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

    每个表达式case后跟一个要匹配的模式。在这个例子中,字符串与操作符从上到下匹配,如果找到这样的匹配,则执行操作符。也可以捕获全部或部分匹配并重新使用它。在我们的示例中,在模式匹配的情况下,unknown_command我们在 f-string中重用了它。

    变量匹配与模式匹配

    如果要将值映射到常量,则应将常量称为类的字段:

    class Command:
        QUIT = 0
        RESET = 1
    
    command = 0
    
    match command:
        case Command.QUIT:
            quit()
        case Command.RESET:
            reset()
    

    如果您尝试在不求助于课程的情况下做到这一点,如下所示:

    QUIT = 0
    RESET = 1
    
    command = 0
    match command:
        case QUIT:
            quit()
        case RESET:
            reset()
    

    获取与名称不属于已知模式相关的错误响应:

    名称捕获“退出”使剩余模式无法访问

    使用模式匹配匹配多个元素

    模式匹配不仅用作字典查找的替代品。它用于描述您想要匹配的内容的结构。因此,您可以根据要匹配的项目数或它们的组合来执行匹配。

    这是一个更复杂的例子。在这里,用户输入一个命令,可能后跟一个文件名:

    command = input()
    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’将输入拆分后获得的元素匹配split()。
    • case [’load’, filename]:检查第一个分隔元素是否为字符串’load’,以及它后面是否跟着第二个字符串。如果有第二行,则将第二行存储在变量中filename并用于进一步的工作。以同样的方式检查case [«save», filename]:。
    • case _:这是通配符匹配。如果在该点之前没有发生其他匹配,则发生匹配。请注意,下划线字符 ( _) 不与任何内容相关联,在这种情况下,下划线用作命令的信号,match即所讨论的大小写是通配符。(这就是我们在块体中引用命令变量的原因case,因为没有捕获任何内容。)

    结构模式匹配中的模式

    模板可以是简单的值,也可以包含更复杂的匹配逻辑。

    这里有些例子:

    • case ’a’:匹配单个值’a’。
    • case [’a’,’b’]:映射到一个集合(collection) [’a’,’b’]。
    • case [’a’, value1]:映射到具有两个值的集合,并将第二个值放入变量value1中。
    • case [’a’, *values]:映射到至少有一个值的集合。剩余值(如果有)存储在values. 请注意,每个模板只能包含一个带有星号的元素。
    • case (’a’|’b’|’c’):运算符or,也称为|,可用于在单个案例块中处理多个调用。这里我们匹配’a’, ’b’, 或’c’。
    • case (’a’|’b’|’c’) as letter:和上面一样,只是我们现在把对应的元素放在letter.
    • case [’a’, value] if ...:只有当表达式为真时,该变量才被绑定。我们要绑定的变量可以在.... 例如,如果我们使用if value in valid_values,那么case只有在捕获的值实际上在valid_values.
    • case [’z’, _]:将匹配任何以 . 开头的元素集合’z’。

    使用模式匹配与对象匹配

    Python 中最先进的模式匹配功能是能够匹配具有特定属性的对象。考虑一个我们正在使用的应用程序media_object。我们想将此对象转换为文件.jpg并从函数中返回。

    match media_object:
        case Image(type="jpg"):
            # Return as-is
            return media_object
        case Image(type="png") | Image(type="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 type {media_object} can't be handled yet")
    

    在上面的每一个中case,我们都在寻找某种类型的对象,有时具有某些属性。Image在第一种情况下,我们正在寻找type属性为的对象的匹配项’jpg’。如果 type 匹配,则第二case个匹配’png’or ’gif’。在第三case个中,检查对象是否符合 type Video,而属性没有值。在最后一种情况下,我们得到了之前没有选择的所有内容。

    您还可以使用对象匹配进行捕获:

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

    有效使用模式匹配

    使用match/casePython 的关键是编写描述您想要使用的结构的模板。简单的常量测试很好,但如果这就是你所做的一切,最好只做一个字典查找。Python 中结构模式匹配的真正价值在于能够匹配对象的模式,而不仅仅是任何一个对象,甚至是它们的集合。

    要记住的另一个重要细节是映射的写入顺序。您首先检查的匹配将影响您的整体匹配的有效性和准确性。首先放置最具体的比较,最后放置最一般的比较。

    最终,如果您有一个可以通过if/elif/else或字典查找解决的问题,那么请使用它们而不是match/case. 模式匹配很强大,但不是通用的。在最有意义的时候使用它。

    您可以在此处阅读有关 Python (PEP 622) 中的模式匹配文档的更多信息。

    原创文章。

    • 5

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5