Python 居然開始抄作業(yè)了,這次抄的是Rust
整個(gè)九月份,我都在忙一個(gè)js的項(xiàng)目。因?yàn)楹枚嗄瓴粚慾s,動(dòng)手之前特地找了一些js的資料惡補(bǔ)半天,結(jié)果發(fā)現(xiàn)js越來越像Python了。且不說js從基于原型的面向?qū)ο筠D(zhuǎn)向了基于類的面向?qū)ο螅瑔问穷愋突瘮?shù)組(Typed Arrays)的引入,就讓用慣了NumPy的我喜出望外。另外,js的數(shù)組推導(dǎo)式和裝飾器,也幾乎是完全照抄了Python的作業(yè)。
進(jìn)入十月,Python社區(qū)指導(dǎo)委員會(huì)正式推出了Python3.10,距離上一個(gè)版本發(fā)布,正好過去了一年。記得Python3.9發(fā)布之后沒幾天,我寫過一篇名為《危險(xiǎn)的轉(zhuǎn)變:Python正在從簡明轉(zhuǎn)向臃腫,從實(shí)用轉(zhuǎn)向媚俗》的博文,著實(shí)吐槽了一番,正所謂愛之也深恨之也切。這次新版本發(fā)布,我自然不會(huì)放過嘗鮮的機(jī)會(huì),趕緊安裝嘗試了一下,卻發(fā)現(xiàn),一向特立獨(dú)行的Python居然開始抄作業(yè)了,這次抄的是Rust。
眾所周知,Rust有兩樣鎮(zhèn)山之寶,一是安全的內(nèi)存模型,二是模式匹配。在內(nèi)存管理上,Python使用了傳統(tǒng)的垃圾回收的內(nèi)存模型,和Rust沒有多少可比性。隨著Python3.10的發(fā)布,模式匹配被引入到Python中,而且?guī)缀跏峭耆瞻崃薘ust的概念。Rust支持模式匹配中的變量綁定、結(jié)構(gòu)體/元組解構(gòu)、守衛(wèi)條件判斷、數(shù)值范圍匹配等特性,Python照單全收,連下劃線 _ 匹配任意情形也原封不動(dòng)地繼承了過來。
讓我們一起來揭開Pyhton3.10最重要的升級(jí)——模式匹配的蓋頭。
類似C語言的switch case, Python的模式匹配最簡單的應(yīng)用就是對(duì)字面值進(jìn)行匹配:
- >>> a = 3
- >>> match(a):
- case 1:
- print("a == 1")
- case 2:
- print("a == 2")
- case _: # default
- print("other")
- other
case語句中,支持或操作:
- >>> import datetime
- >>> n = datetime.datetime.now()
- >>> match(n.weekday()):
- case 0|1|2|3|4: print("工作日")
- case 5|6: print("周末")
- 工作日
除了字面值外,case語句,支持對(duì)上面提到的模式進(jìn)行解構(gòu),如對(duì)元組:
- >>> a = (0, 1)
- >>> match(a):
- case (0, y): # 匹配所有第0個(gè)元素是0的元組
- print(f"a[0]==0, a[1]=={y}")
- case (x, 0): # 匹配所有第1個(gè)元素是0的元組
- print(f"a[1]==0, a[0]=={x}")
- a[0]==0, a[1]==1
對(duì)列表:
- >>> cmd = "ls test"
- >>> match(cmd.split()):
- case ["ls", path]: print(f"顯示{path}中的文件和目錄")
- case ["rm", path]: print(f"刪除{path}中的文件和目錄")
- case ["cp", src, dest]: print(f"將{src}復(fù)制到{dest}")
- 顯示test中的文件和目錄
對(duì)字典:
- >>> a = {"name": "xxx", "age": 40, "job": "程序員"}
- >>> match(a):
- case {"name": name, "age": age, "job": "程序員"}:
- print(f"他是一名程序員,名字叫{name}, {age}歲了")
- case {"name": name, "age": age, "job": "教師"}:
- print(f"他是一名人民教師,名字叫{name}, {age}歲了")
- 他是一名程序員,名字叫xxx, 40歲了
對(duì)于類對(duì)象,match case照樣可以使用如:
- >>> class Point():
- def __init__(self,x,y):
- self.x = x
- self.y = y
- >>> a = Point(1, 2)
- >>> match(a):
- case Point(x=1, y=y): print(f"這是一個(gè)X坐標(biāo)為1的點(diǎn),它的Y坐標(biāo)為{y}")
- case Point(x=x, y=2): print(f"這是一個(gè)Y坐標(biāo)為2的點(diǎn),它的X坐標(biāo)為{x}")
- 這是一個(gè)X坐標(biāo)為1的點(diǎn),它的Y坐標(biāo)為2
也可以用于多個(gè)類:
- >>> class Programmer:
- def __init__(self, lang):
- self.lang = lang
- >>> class Teacher:
- def __init__(self, subject):
- self.subject = subject
- >>> a = Programmer("Python")
- >>> match(a):
- case Programmer(lang="Python"): print("咱們都是Pyhon程序員!")
- case Programmer(): print("原來你也是一名程序員!")
- case Teacher(): print("向人民教師致敬!")
- 咱們都是Pyhon程序員!
case 語句后,還支持添加一個(gè)if語句,進(jìn)一步對(duì)匹配的條件進(jìn)行限制,這個(gè)if語句,被稱之為“守衛(wèi)”。如:
- >>> class Point():
- def __init__(self,x,y):
- self.x = x
- self.y = y
- >>> a = Point(2,2)
- >>> match(a):
- case Point(x=x, y=y) if x==y: print("這個(gè)點(diǎn)在斜率為1的直線上")
- case Point(x=x, y=y) if x==-y: print("這個(gè)點(diǎn)在斜率為-1的直線上")
- 這個(gè)點(diǎn)在斜率為1的直線上
美中不足的是,我沒有找到case語句中直接使用范圍的方法,但這個(gè)可以用守衛(wèi)來解決:
- >>> a = 5
- >>> match(a):
- case x if 1 <= x < 10: print("數(shù)字在1和10之間")
- case x if 10 <= x < 20: print("數(shù)字在10和20之間")
- 數(shù)字在1和10之間