整个九月份,我都在忙一个js的项目。因为好多年不写js,动手之前特地找了一些js的资料恶补半天,结果发现js越来越像Python了。且不说js从基于原型的面向对象转向了基于类的面向对象,单是类型化数组(Typed Arrays)的引入,就让用惯了NumPy的我喜出望外。另外,js的数组推导式和装饰器,也几乎是完全照抄了Python的作业。
进入十月,Python社区指导委员会正式推出了Python3.10,距离上一个版本发布,正好过去了一年。记得Python3.9发布之后没几天,我写过一篇名为《危险的转变:Python正在从简明转向臃肿,从实用转向媚俗》的博文,着实吐槽了一番,正所谓爱之也深恨之也切。这次新版本发布,我自然不会放过尝鲜的机会,赶紧安装尝试了一下,却发现,一向特立独行的Python居然开始抄作业了,这次抄的是Rust。
众所周知,Rust有两样镇山之宝,一是安全的内存模型,二是模式匹配。在内存管理上,Python使用了传统的垃圾回收的内存模型,和Rust没有多少可比性。随着Python3.10的发布,模式匹配被引入到Python中,而且几乎是完全照搬了Rust的概念。Rust支持模式匹配中的变量绑定、结构体/元组解构、守卫条件判断、数值范围匹配等特性,Python照单全收,连下划线 _ 匹配任意情形也原封不动地继承了过来。
让我们一起来揭开Pyhton3.10最重要的升级——模式匹配的盖头。
类似C语言的switch case, Python的模式匹配最简单的应用就是对字面值进行匹配:
- >>>a=3
- >>>match(a):
- case1:
- print("a==1")
- case2:
- print("a==2")
- case_:#default
- print("other")
- other
case语句中,支持或操作:
- >>>importdatetime
- >>>n=datetime.datetime.now()
- >>>match(n.weekday()):
- case0|1|2|3|4:print("工作日")
- case5|6:print("周末")
- 工作日
除了字面值外,case语句,支持对上面提到的模式进行解构,如对元组:
- >>>a=(0,1)
- >>>match(a):
- case(0,y):#匹配所有第0个元素是0的元组
- print(f"a[0]==0,a[1]=={y}")
- case(x,0):#匹配所有第1个元素是0的元组
- print(f"a[1]==0,a[0]=={x}")
- a[0]==0,a[1]==1
对列表:
- >>>cmd="lstest"
- >>>match(cmd.split()):
- case["ls",path]:print(f"显示{path}中的文件和目录")
- case["rm",path]:print(f"删除{path}中的文件和目录")
- case["cp",src,dest]:print(f"将{src}复制到{dest}")
- 显示test中的文件和目录
对字典:
- >>>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岁了
对于类对象,match case照样可以使用如:
- >>>classPoint():
- def__init__(self,x,y):
- self.x=x
- self.y=y
- >>>a=Point(1,2)
- >>>match(a):
- casePoint(x=1,y=y):print(f"这是一个X坐标为1的点,它的Y坐标为{y}")
- casePoint(x=x,y=2):print(f"这是一个Y坐标为2的点,它的X坐标为{x}")
- 这是一个X坐标为1的点,它的Y坐标为2
也可以用于多个类:
- >>>classProgrammer:
- def__init__(self,lang):
- self.lang=lang
- >>>classTeacher:
- def__init__(self,subject):
- self.subject=subject
- >>>a=Programmer("Python")
- >>>match(a):
- caseProgrammer(lang="Python"):print("咱们都是Pyhon程序员!")
- caseProgrammer():print("原来你也是一名程序员!")
- caseTeacher():print("向人民教师致敬!")
- 咱们都是Pyhon程序员!
case 语句后,还支持添加一个if语句,进一步对匹配的条件进行限制,这个if语句,被称之为“守卫”。如:
- >>>classPoint():
- def__init__(self,x,y):
- self.x=x
- self.y=y
- >>>a=Point(2,2)
- >>>match(a):
- casePoint(x=x,y=y)ifx==y:print("这个点在斜率为1的直线上")
- casePoint(x=x,y=y)ifx==-y:print("这个点在斜率为-1的直线上")
- 这个点在斜率为1的直线上
美中不足的是,我没有找到case语句中直接使用范围的方法,但这个可以用守卫来解决:
- >>>a=5
- >>>match(a):
- casexif1<=x<10:print("数字在1和10之间")
- casexif10<=x<20:print("数字在10和20之间")
- 数字在1和10之间
原文链接:https://mp.weixin.qq.com/s/kXblwnxsphb00ATDPfsdTA