写点什么

它终于来了!

发布于: 2021 年 03 月 22 日
它终于来了!

前言

众所周知,大多数语言都是 switch-case 语句,但是作为红极一时的 Python,它却没有。今天,它终于来了。2021 年 2 月 8 日,指导委员会通过了 PEP 634, PEP635, PEP636,至此,Python 总算拥有了功能和 switch-case 相同的 match-case, 我们再也不用再写一连串的 if-else 了。

展示

单个匹配

即用一个参数同多种属性进行比较。

def http_error(status):    match status:        case 400:            return "Bad request"        case 401:            return "Unauthorized"        case 403:            return "Forbidden"        case 404:            return "Not found"        case 418:            return "I'm a teapot"        case _:            return "Something else"
复制代码


如上,其中 case _意为当其他 case 都无法匹配时,就匹配这条,可以达到永远不会匹配失败的效果。

多个匹配

即使用 | 将多个匹配值组合起来。

...        case 401|403|404:            return "Not allowed"
复制代码


模式匹配

模式也可以是解包操作,用于绑定变量。

# 主题表达式是一个(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")
复制代码


注意,第一个模式中有两个字面量,可以看作是上述普通模式的加强版。但是后两个模式有些不同,元组中一个是字面量一个是变量,这个变量会捕获主题元组中的值。同理,第四个模式 case (x, y) 会捕获两个值,这在理论上与解包作业相似,就如同 point(x, y) = point

数据类型匹配

如果使用了结构数据类,比如 dataclasses,可以用类似于构造函数 类名+参数列表 的形式,但是用来捕获变量。

from dataclasses import dataclass
@dataclassclass Point: x: int y: int
def whereis(point): match point: case Point(0, 0): print("Origin") case Point(0, y): print(f"Y={y}") case Point(x, 0): print(f"X={x}") case Point(): print("Somewhere else") case _: print("Not a point")
复制代码


关键字参数匹配

也可以使用关键字参数。下列关于 y, var 的模式都是等价的,并且都将属性绑定到了变量上。

Point(1, var)Point(1, y=var)Point(x=1, y=var)Point(y=var, x=1)
复制代码


模式嵌套

模式可以被简单粗暴的嵌套起来,例如我们有一组 points 的列表,就可以像这样匹配。

match points:    case []:        print("No points")    case [Point(0, 0)]:        print("The origin")    case [Point(x, y)]:        print(f"Single point {x}, {y}")    case [Point(0, y1), Point(0, y2)]:        print(f"Two on the Y axis at {y1}, {y2}")    case _:        print("Something else")
复制代码


条件模式

给模式添加 if 从句以充当门卫。如果为假,就移步到下一个 case。注意,模式捕获值发生在从句执行前。

match point:    case Point(x, y) if x == y:        print(f"Y=X at {x}")    case Point(x, y):        print(f"Not on the diagonal")
复制代码


子模式

子模式可以使用 as 捕获。

case (Point(x1, y1), Point(x2, y2) as p2): ...
复制代码


常量模式

模式可以使用命名的常量,且必须使用.以防止被解释为捕获变量。

from enum import Enumclass Color(Enum):    RED = 0    GREEN = 1    BLUE = 2
match color: case Color.RED: print("I see red!") case Color.GREEN: print("Grass is green") case Color.BLUE: print("I'm feeling the blues :(")
复制代码


等同 is

某些字面量会被特殊对待,例如 None, False, True,是使用 is 完成匹配的。

例如:

match b:    case True:        print("Yes!")
复制代码


就完全等价与这样

  ...    if b is True:        print("Yes!")
复制代码


发布于: 2021 年 03 月 22 日阅读数: 14
用户头像

大帅比一个! 2018.10.14 加入

混迹于云原生领域的测试开发。

评论

发布
暂无评论
它终于来了!