首页 > 解决方案 > Python 中 switch/case 的语法等价物是什么?

问题描述

C/C++、C#、Java、JavaScript 和 Pascal 参考等编程语言具有switchcase语句(有时也称为selector inspect)的组合,允许您根据多个条件检查一个值以执行某些操作。

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这样的功能等价物,是否存在与上述编程结构的纯语法等价物?

标签: pythonsyntaxswitch-statementconditional-statementspattern-matching

解决方案


TL;博士

Python 3.10.0 (alpha62021 年 3 月 30 日发布)开始,Python 有一个官方的语法等价物,称为match.

基本语法是:

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

对于较旧的 Python 版本,只有在您不想使用if- elif-时才有解决方法else。请参阅此出色的社区帖子以获取一些集合。

例子

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语句的语言通常会执行值匹配的每个案例 - 从上到下。因此,如果您不想失败,还有第三个语句 - break- 可用于switch-构造:case

    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-匹配一个案例 _ _ _ _ _ _

Python 增强提案 (PEP) 编号中提供的规范和信息。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 文档中提到了其中一些有趣的用例。

结语

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

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

附录

尝试 Python 3.10.0

对于 Windows 和 macOS 用户,此页面提供官方安装程序下载。

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不同的版本替换。


推荐阅读