Python 中 switch/case 的语法等价物是啥? [复制]

Posted

技术标签:

【中文标题】Python 中 switch/case 的语法等价物是啥? [复制]【英文标题】:What is the syntactical equivalent to switch/case in Python? [duplicate]Python 中 switch/case 的语法等价物是什么? [复制] 【发布时间】:2021-06-26 20:02:51 【问题描述】:

C/C++、C#、Java、javascript 和 Pascal 等编程语言 (Reference) 组合了 switchcase 语句(有时也称为 select 或 @ 987654328@),它允许您根据多个条件检查一个值以执行某些操作。

my_value = 10;
switch(my_value) 
    case 10:
        print("The number is ten");
    case 2*10:
        print("The number is the double of ten");
    case 100:
        print("The number is one hundred");
    default:
        print("The number is none of 10, 2*10 or 100");

描述switch-case构造的特殊语法的伪代码。

了解dictionary-lookups 等功能等效项后,是否存在与上述编程结构等效的纯句法

【问题讨论】:

注意:我认为这个问题不是重复的,因为我明确要求一种仅语法的方式来完成这个控制流结构.由于所有其他热门问题都不允许更多答案,而且许多人只是查找第一个答案 - 没有阅读所有 cmets - 他们可能找不到这个新的官方解决方案。因此,这篇自我回答的帖子旨在成为对一般问题的新标准“一站式”答案,几乎涵盖了所有方面,以便从初学者到经验丰富的开发人员的每个人都能找到他们需要的东西。 这能回答你的问题吗? Replacements for switch statement in Python? 无法为问题添加新答案并不意味着有必要提出新问题。对社区帖子进行了编辑,在我看来,这比创建基本上重复的新问题更可取。如果我们为语言中的每个功能更改创建一个新的问题和答案,那么将会变得一团糟,因为对于一种语言的每个版本,您将不得不搜索不同的问题,而不是拥有一个不断更新的源。感谢您的回答,非常感谢您抽出宝贵的时间来编写它,但如果您编辑了***社区答案,我更愿意 感谢您的诚实意见,凯文。不幸的是,我认为我的***编辑被拒绝了。不过,对于未来,您的方法似乎是可行的方法 - 谢谢。 Python 3.10 (2021) has it. 【参考方案1】:

TL;DR

Python 3.10.0 (alpha6 released 2021 年 3 月 30 日)开始,Python 有一个官方的等效语法,称为 match

基本语法是:

match value:
    case condition:
        action(s)
    ...

对于较旧的 Python 版本,如果您不想求助于 if-elif-else,则只有解决方法。 请参阅这个出色的 community post 以获取一些集合。

示例

my_value = 10
match my_value:
    case 10:
        print("The number is ten")
    case 2*10:
        print("The number is the double of ten")
    case 100:
        print("The number is one hundred")
    case _:
        # this is the default handler if none
        # of the above cases match.
        print("The number is none of 10, 2*10 or 100")

因此,涉及变通办法的其他答案不再有效 - 从性能的角度来看也是如此。

重要提示

如果来自支持switchcase 的语言,您可能已经知道它们的行为。不过,对于 Python,有一些差异需要注意。

案件不会落空

具有switch-case 语句的语言通常会执行每个值匹配的情况 - 从上到下。因此,如果您不想失败,可以在 switch-case 构造中使用第三条语句 - break

value = 10
switch (value) 
    case 10:
        print("Value is ten");
    case 2*5:
        print("Value is the double of five");
        break;
    case 20/2:
        print("Value is the half of twenty");
    default:
        print("This is just the default action.");

在此示例中,将执行前 两个 案例,因为第一个案例失败了。如果在第二种情况下没有break 语句,则将执行所有情况,包括默认情况。

在 Python 中,只执行第一个匹配的案例。你可以把它想象成每个案例都包含一个隐藏的break 语句。

变量引用不能作为条件使用

base_color = "red"
chosen_color = "green"
match chosen_color:
    case base_color:
        print("Yes, it matches!")

这段代码确实打印出颜色匹配!

裸变量引用,因为大小写条件始终匹配。

无论如何,像 case "red": ... 这样的文字和像 case AllColors.red 这样的限定(即虚线)名称的工作方式与预期一样 - 无需害怕它们。

所有这一切都是如此,因为 Python 软件基金会并没有决定只是复制另一个无聊的控制流模型,而是实际实现一个成熟的模式匹配器,它不仅仅是一个switch-case 声明。更多信息请参见下一节。

强大的模式匹配

match - Match ain't case h哎哟

Python Enhancement Proposals (PEP) nos. 634-636中提供的规格和信息

在 Python 中,match 实际上不仅仅是一个简单的开关——因此可能是这个名字。它具有特殊功能,例如深层占位符和通配符。

受阅读文档启发的示例 - 所以您不必:

match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print("Our current Y position is", y, " now.")

您可以匹配任意嵌套的数据结构,包括占位符。在上面的示例中,我们正在匹配一个包含两个项目的元组,在第二种情况下,我们使用占位符 y 来获取匹配时分配的值。

您也可以匹配类属性,以非常相似的方式:

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("The point lies on the y axis at a height of", y, "units.")

这也解释了为什么您不能在 case 条件下匹配单个变量引用:您实际上并没有匹配该变量的值,而是实际上引入了同名的占位符! 因此,如果您要像这样打印chosen_color

base_color = "red"
chosen_color = "green"
match chosen_color:
    case base_color:
        print("Our base color is", base_color)

它实际上会打印出来

我们的底色是绿色

因为base_color 现在是一个占位符,它被分配了chosen_color 的值。

这种高级模式匹配还有很多用例,Python documentation 中提到了其中的一对。

结语

Python 3.10 得到应有的采用还需要一段时间。 Python 3.10.0 将于 2021 年 10 月 4 日稳定发布 - 这意味着它可能包含在 Ubuntu 22.04 及更高版本中。

如果您只是想自己动手编写程序,请将它们部署到您自己的服务器上,或者如果您打算以打包的形式而不是作为纯源代码文件分发您的作品,请尝试一下这个新功能你的程序 - 这将是一个好处!

附录

尝试 Python 3.10.0

对于 Windows 和 macOS 用户,this page 提供官方安装程序下载。

在 Debian 和 Ubuntu 上,您可以使用非常流行的“DeadSnakes”项目 PPA:

sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.10
python3.10 --version

在不破坏系统的情况下尝试 Python 3.10.0

Docker 是在完全隔离的环境中使用 Python 3.10 的一个选项,无需任何复杂的设置步骤。

docker run -it python:3.10.0a6-alpine

就是这样。随着时间的推移,可能会发布新的 alpha 或 beta 版本。然后,您需要将 a6 替换为 different version。

【讨论】:

在我注意到你自己回答之前,我正要评论说这似乎是一个无可挑剔的定时问题(考虑到它距离 Alpha 版发布还不到一天)!很好的答案,感谢您将其添加到 SO python 知识库。 :) 是的,碰巧看到 alpha 公告并对这个新的强大功能感到非常兴奋,我认为值得将它介绍给 SO Python 社区 - 感谢您的评论。 :)【参考方案2】:

Pre-Python 3.10.0 答案

没有。它通常以两种方式完成,具体取决于代码上下文:

1。 if/elif:

使用 if/elif 语法,您可以获得最相似的 switch case 版本:

my_value = 10;
if my_value == 10:
    print("The number is ten")
elif my_value == 2*10:
    print("The number is the double of ten")
elif my_value == 100:
    print("The number is one hundred")
else:
    print("The number is none of 10, 2*10 or 100")

2。字典查找:

另一种不太常见的方法是制作一个字典,并在 switch/case 的每个条件下分配一个要调用的相应函数:

my_value = 10;

def def_action():
    print("The number is none of 10, 2*10 or 100")

def ten_action():
    print("The number is ten")

def double_ten_action():
    print("The number is ten")

def hundred_action():
    print("The number is one hundred")


    10: ten_action,
    2*10: double_ten_action,
    100: hundred_action,
.get(
    my_value,
    def_action # This is the final else, if no match if found
)()

尽管Pythonic 较少,但当在各种情况下您有很多代码会降低可读性时,这很有用。

【讨论】:

以上是关于Python 中 switch/case 的语法等价物是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

C++ switch...case语法的坑(crosses initializationjump to case label)变量作用域问题

Python 类似switch/case语句实现方法 获取文件内容匹配函数并执行

PythonStudy——Python 中Switch-Case 结构的实现

switch case 语句

Python里怎么实现switch case

switch...case跳转表