刚刚,Python 3.10 正式发布了!我发现了一个可怕的功能...
“
閱讀本文大概需要 8 分鐘。
”就在前幾天( 2021年10月4日) Python 終于正式發布了 3.10 版本,看了下這個版本的一些特性,最受關注的應該就是 結構模式匹配 了吧?也就是大家所熟悉的switch-case,寫錯了不好意思,是 match-case。
下邊是最簡單的一個 match-case 的例子,看起來是不是非常的直觀簡潔?
def?http_error(status):match?status:case?400:print("Bad?request")case?404:print("Not?found")case?418:print("I'm?a?teapot")case?_:print("Something's?wrong?with?the?internet")對這個功能滿懷期待的我,趕緊就下載升級了 3.10 的 Python 趕緊試用,可沒想到在我深入的體驗過后,我從最開始的期待,變成了敬畏。
敬畏,是因為這樣一個看似簡單的新功能,卻有著不少的學習成本,并且對 結構模式匹配 半知半解的人來說,會增大代碼出錯的概率,并不是大數人都能輕松駕馭的。
我為什么會這么說呢?我會在文章最后來簡述我的觀點。
鑒于大多數人,都沒有實際用過這種 結構模式匹配,我會從 升級 3.10 開始教大家如何嘗鮮這個新功能,然后我會詳細的介紹 match-case 的使用方法。
?1. 升級 3.10 新版本
我本機的電腦上目前的 Python 版本是 3.9.1 的
$?/usr/local/bin/python3?--version Python?3.9.1由于這邊我使用的是 mac,因此我從官網上下載的是 Python 3.10 的 pkg 文件,如果是 win 的用戶,可以下載相應的 msi 或者 exe 文件。
下載鏈接我貼在下邊,可以直接訪問下載
mac:?https://www.python.org/ftp/python/3.10.0/python-3.10.0-macos11.pkg win:?https://www.python.org/ftp/python/3.10.0/python-3.10.0-amd64.exe我下載好安裝文件后,雙擊安裝,之后就雙擊下載的 pkg 文件,進入安裝流程
一路點擊繼續,該同意的同意一下,出現如下提示表示安裝成功。
再次在終端上確認下是否升級成功
?2. or 模式的使用
在上面我已經貼出一個 match-case 的最簡單示例,這邊就直接跳過簡單示例,來說說那些比較特殊的用法。
在 Python 3.10 中其實有新增一個 聯合類型操作符 | ,但這個只能用于類型,具體的用法,我會在下一篇文章中做詳細的介紹,本篇文章還是集中于 match-case 的使用。
在學習match-case 的時候,你會發現,也有一個類似于聯合類型操作符的用法,但請你要注意區別,它并不是聯合類型操作,而是在 match-case 下獨有的 or模式操作符 | ,它可以將多個具體相同邏輯的 case 語句簡寫成同一個
match?status:case?401?|?403?|?404:print("Not?allowed")case?_:print("Something's?wrong?with?the?internet")?3. 通配符匹配任意對象
match-case 的出現有利于提高代碼的可讀性,讓你的代碼更加優雅,但同時要使用好它,也是有一些門檻的,特別是通配符的使用。
下邊我舉一些例子來進行講解
在如下代碼中,使用了通配符 _ 和 可變參數中的 ?* 符號
import?sysmatch?sys.argv[1:]:case?["quit"]:print("exit")case?["create",?user]:?????#?創建單個用戶print("create",?user)case?["create",?*users]:??#?批量創建多個用戶for?user?in?users:print("create",?user)case?_:print("Sorry,?I?couldn't?understand?the?argv")最后一個 case 中的 _ 并不作為變量名,而表示一種特殊的模式,在前面的 case 中都未命中的情況下,該 case 會是最后的保障,能確保命中,它相當于 Go 語言中的 default 分支。
import?"fmt"func?main()?{education?:=?"本科"switch?education?{case?"博士":fmt.Println("我是博士")case?"研究生":fmt.Println("我是研究生")case?"本科":fmt.Println("我是本科生")case?"大專":fmt.Println("我是大專生")default:fmt.Println("學歷未達標..")} }?4. 使用可變參數 *args
第二個 case 和 第三個 case 非常的像,區別在于第三個 case中 users 前加了個 *,他跟原 Python 函數中的可變參數是一個用法,會匹配列表的多個值。
在該中表示可以從命令行參數中批量創建用戶。
在 match-case 中相應的 case 若有運行到,對應的變量是會被創建的。比如
?5. 使用可變參數 **kv
在如下代碼中,**rest 會匹配到所有的 args 中的 key 和 value
?6. 長度的匹配方式
若你希望使用 case 僅對對象的長度做一些匹配,可以使用下面這樣的方式
[*_] 匹配任意長度的 list;
(, , *_) 匹配長度至少為 2 的 tuple。
?7. 類對象的匹配
對于類對象的匹配,下邊這個例子足夠簡單,不再講解。
?8. 匹配要注意順序
在上邊基本介紹完了 match-case 的使用方法,如需更詳細的內容,不如去通讀下 PEP?636(https://www.python.org/dev/peps/pep-0636/)?的內容。
在文章最開始的時候,我說過開發者應該對這些新特性 心存敬畏,match-case 這樣一個看似簡單的新功能,卻有著不少的學習成本,如果對 結構模式匹配 半知半解的人來說,可能會增大代碼出錯的概率,并不是大數人都能輕松駕馭的。
之所以會這么說,是因為 match-case 在面對不同的對象,它的匹配的規則也有所不同。
當 match 的對象是一個 list 或者 tuple 的時候,需要長度和元素值都能匹配,才能命中,這就是為什么下面這個例子走的是第三個 case 而不是第二個 case。
當 match 的對象是一個 dict 的時候,規則卻有所不同,只要 case 表達式中的 key 在所 match 的對象中有存在,即可命中。
而當 match 的對象是類對象時,匹配的規則是,跟 dict 有點類似,只要對象類型和對象的屬性有滿足 case 的條件,就能命中。
因此在寫 match-case 的時候,最大的難點可能就是如何把握這個順序,才能確保你寫的代碼不會翻車。
我個人總結一些規律,僅供大家參考:
list 或者 tuple:應該從不格式到嚴格
dict 或者 object:應該從嚴格到不嚴格
在經過半天時間的嘗鮮后,我有了一些自己的理解,分享給大家,不知道我的理解有沒有問題,但我依然建議大家在 充分了解 match-case 的匹配規則 后,再去使用它。
E?N?D
各位伙伴們好,詹帥本帥假期搭建了一個個人博客和小程序,匯集各種干貨和資源,也方便大家閱讀,感興趣的小伙伴請移步小程序體驗一下哦!(歡迎提建議)
推薦閱讀
牛逼!Python常用數據類型的基本操作(長文系列第①篇)
牛逼!Python的判斷、循環和各種表達式(長文系列第②篇)
牛逼!Python函數和文件操作(長文系列第③篇)
牛逼!Python錯誤、異常和模塊(長文系列第④篇)
總結
以上是生活随笔為你收集整理的刚刚,Python 3.10 正式发布了!我发现了一个可怕的功能...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不飘了,让图像识别算法快速产业落地别再实
- 下一篇: Pandas数据探索分析,分享两个神器!