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

有很多人期待在 Python 中使用 switch-case 語句,Python 社區裏針對它有過長達數年的討論(PEP-275、PEP-3103),然而結論是不支持。最近,官方終於通過了 PEP,Python 將要迎來一次重大更新!match-case 與 switch-case 的結構相似,然而其思想與用途有着巨大差別。有人喜歡,有人憎惡。今天分享一篇文章,讓大家見識一下這個新東西到底有什麼本事。

前言

2021 年 2 月 8 日,指導委員會通過了 PEP 634, PEP635, PEP636,至此,Python 總算擁有了 match-case, 不用再寫一連串的 if-else 了

嘿餵狗

1

最簡單的形式如下,將 match 主題表達式與一個或多個字面量模式進行比較

 1def http_error(status):  
 2    match status:  
 3        case 400:  
 4            return "Bad request"  
 5        case 401:  
 6            return "Unauthorized"  
 7        case 403:  
 8            return "Forbidden"  
 9        case 404:  
10            return "Not found"  
11        case 418:  
12            return "I'm a teapot"  
13        case _:  
14            return "Something else"  
15

最後一個 case 中,case _:類似於 C 和 Java 中的default:,永遠不會匹配失敗,即當其他 case 都無法匹配時,匹配這條

2

可以使用|將多個字面量組合起來表示或

1...  
2        case 401|403|404:  
3            return "Not allowed"  
4
5

3

模式也可以是解包操作,用於綁定變量

 1# 主題表達式是一個(x, y)元組  
 2match point:  
 3    case (0, 0):  
 4        print("Origin")  
 5    case (0, y):  
 6        print(f"Y={y}")  
 7    case (x, 0):  
 8        print(f"X={x}")  
 9    case (x, y):  
10        print(f"X={x}, Y={y}")  
11    case _:  
12        raise ValueError("Not a point")  
13
14

注意,第一個模式中有兩個字面量,可以看作是上述普通模式的加強版。但是後兩個模式有些不同,元組中一個是字面量一個是變量,這個變量會捕獲主題元組中的值。同理,第四個模式case (x, y):會捕獲兩個值,這在理論上與解包作業相似,就如同point(x, y) = point

4

如果使用了結構數據類,比如data classes,可以用類似於構造函數'類名 + 參數列表'的形式,但是用來捕獲變量

 1from dataclasses import dataclass  
 2
 3  @dataclass  
 4class Point:  
 5    x: int  
 6    y: int  
 7
 8  def whereis(point):  
 9    match point:  
10        case Point(0, 0):  
11            print("Origin")  
12        case Point(0, y):  
13            print(f"Y={y}")  
14        case Point(x, 0):  
15            print(f"X={x}")  
16        case Point():  
17            print("Somewhere else")  
18        case _:  
19            print("Not a point")  
20

5

也可以使用關鍵字參數。下列關於y, var的模式都是等價的,並且都將屬性綁定到了變量上

1Point(1, var)  
2Point(1, y=var)  
3Point(x=1, y=var)  
4Point(y=var, x=1)  
5
6

6

模式可以被簡單粗暴的嵌套起來,例如我們有一組 points 的列表,就可以像這樣匹配

 1match points:  
 2    case []:  
 3        print("No points")  
 4    case [Point(0, 0)]:  
 5        print("The origin")  
 6    case [Point(x, y)]:  
 7        print(f"Single point {x}, {y}")  
 8    case [Point(0, y1), Point(0, y2)]:  
 9        print(f"Two on the Y axis at {y1}, {y2}")  
10    case _:  
11        print("Something else")  
12
13

7

給模式添加 if 從句以充當門衛。如果爲假,就移步到下一個 case。注意,模式捕獲值發生在從句執行前

1match point:  
2    case Point(x, y) if x == y:  
3        print(f"Y=X at {x}")  
4    case Point(x, y):  
5        print(f"Not on the diagonal")  
6
7

8

子模式可以使用as捕獲

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

9

模式可以使用命名的常量,且必須使用.以防止被解釋爲捕獲變量

 1from enum import Enum  
 2class Color(Enum):  
 3    RED = 0  
 4    GREEN = 1  
 5    BLUE = 2  
 6
 7  match color:  
 8    case Color.RED:  
 9        print("I see red!")  
10    case Color.GREEN:  
11        print("Grass is green")  
12    case Color.BLUE:  
13        print("I'm feeling the blues :(")  
14

10

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

1match b:  
2    case True:  
3        print("Yes!")  
4
5

就完全等價於這樣

1    if b is True:  
2        print("Yes!")
3
4

多謝

關於 match-case 的用法可能已過時或理解不準確,如有錯漏地方歡迎指正,共同學習,權威及最新信息可關注 Guido 老爺子的官方 repo[1]

參考資料

[1]

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

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/_o6-B7DxTlTikQvGK-pNwg