Python重大变化:是match-case,不是switch-case

Python猫

共 6486字,需浏览 13分钟

 ·

2021-03-01 15:31

 △点击上方“Python猫”关注 ,回复“2”加入交流群
花下猫语:有很多人期待在 Python 中使用 switch-case 语句,Python 社区里针对它有过长达数年的讨论(PEP-275、PEP-3103),然而结论是不支持。我曾在文章Python 为什么不支持 switch 语句?》里专门讨论了此话题。在那篇文章末尾,我还介绍了当时仍在草案阶段的模式匹配语法。最近,官方终于通过了PEPPython 将要迎来一次重大更新!match-caseswitch-case 的结构相似,然而其思想与用途有着巨大差别。有人喜欢,有人憎恶。今天分享一篇文章,让大家见识一下这个新东西到底有什么本事?

作者:不羁的凉皮儿

来源:不羁的学习


前言

2021 年 2 月 8 日,指导委员会通过了 PEP 634, PEP635, PEP636,至此,Python 总算拥有了 match-case, 不用再写一连串的 if-else 了

嘿喂狗

#1

最简单的形式如下,将 match 主题表达式与一个或多个字面量模式进行比较

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 _:类似于 C 和 Java 中的default:,永远不会匹配失败,即当其他 case 都无法匹配时,匹配这条

#2

可以使用|将多个字面量组合起来表示或

        ...
        case 401|403|404:
            return "Not allowed"

#3

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

# 主题表达式是一个(x, y)元组
match point:
    case (00):
        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

#4

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

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

def whereis(point):
    match point:
        case Point(00):
            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")

#5

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

Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)

#6

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

match points:
    case []:
        print("No points")
    case [Point(00)]:
        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")

#7

给模式添加 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")

#8

子模式可以使用as捕获

case (Point(x1, y1), Point(x2, y2) as p2): ...

#9

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

from enum import Enum
class 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 :(")

#10

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

例如:

match b:
    case True:
        print("Yes!")

就完全等价于这样

    ...
    if b is True:
        print("Yes!")

多谢

关于 match-case 的用法可能已过时或理解不准确,如有错漏地方欢迎指正,共同学习,权威及最新信息可关注Guido 老爷子的官方 repo[1]

参考资料

[1]

Guido老爷子的官方repo: https://github.com/gvanrossum/patma

近两年里,我原创和翻译了130+技术文章,主要关注Python进阶、小技巧、编程设计、PEP翻译、Python哲学等话题。现已集结出了一本电子书《优雅的Python》,请回复数字『1』,获取下载地址。

近期热门文章推荐:

Python 有可能删除 GIL 吗?
Python 没有指针,如何解算法题?
Python 为什么推荐蛇形命名法?
Python 中如何实现参数化测试?
如何通过测试提升 Python 代码的健壮性

分享在看是对我最大的支持!

浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报