2021年10月4日Python终于正式发布了3.10版本。看了这个版本的一些特性,最关心的应该是结构模式匹配吧?这是每个人都熟悉的开关盒。抱歉打错了,是匹配案例。下面是一个最简单的match-case例子,是不是看起来很直观简洁?defhttp_error(status):matchstatus:case400:print("Badrequest")case404:print("Notfound")case418:print("I'mateapot")case_:print("Something'swrongwiththeinternet")我很期待这个功能,并赶紧下载并升级了Python3.10试用了一下,没想到深入体验之后,从一开始的期待变成了敬畏。敬畏,因为这样一个看似简单的新功能却有很大的学习成本,而且对于结构模式匹配一??知半解的人来说,会增加代码出错的概率,不是一般人能够轻松驾驭的。我为什么这么说?我会在文末简要说明我的观点。由于大多数人从来没有真正使用过这种结构模式匹配,所以我将从3.10升级开始教你如何尝试这个新特性,然后我会详细介绍match-case的使用。1.升级到新版本3.10。我本地电脑当前的Python版本是3.9.1$/usr/local/bin/python3--versionPython3.9.1由于我这里用的是mac,所以我从官网下载的是Python3.10的pkg文件。如果你是win用户,可以下载对应的msi或exe文件。下载链接我贴在下面,大家可以直接访问下载mac:https://www.python.org/ftp/python/3.10.0/python-3.10.0-macos11.pkgwin:https://www.python.org/ftp/python/3.10.0/python-3.10.0-amd64.exe我下载安装文件后,双击安装,然后双击下载的pkg文件进入安装过程,点击继续。出现以下提示表示安装成功。再次在终端查看是否升级成功。2.or模式的使用上面我贴出了一个最简单的match-case例子,这里就跳过这个简单的例子,说说那些特殊的用法。在Python3.10中,其实有一个新的联合类型运算符|,但这只能用于类型。具体用法我会在下一篇文章详细介绍。本文还是重点介绍match-case的使用。在学习match-case的时候,你会发现也有类似union类型运算符的用法,但是请注意区别,不是union类型的运算,而是match-case|下的uniqueormode运算,它可以将具有相同特定逻辑的多个case语句缩短为相同的matchstatus:case401|403|404:print("Notallowed")case_:print("Something'swrongwiththeinternet")3.Wildcardmatchesanyobjectmatch-大小写的出现有助于提高代码的可读性,让你的代码更加优雅,但同时,要用好它也有一些障碍,尤其是通配符的使用。下面我举几个例子来说明。在下面的代码中,使用了变量参数中的通配符_和*符号。importsysmatchsys.argv[1:]:case["quit"]:print("exit")case["create",user]:#创建单个用户print("create",user)case["create",*users]:#批量创建多个用户foruserinusers:print("create",user)case_:print("Sorry,Icouldn'tunderstandstandtheargv")最后一个案例中的_不作为变量名,而是代表一种特殊模式.在前面的case都漏掉的情况下,这个case就是最后的保证,可以保证命中。相当于Go语言中的默认分支。import"fmt"funcmain(){education:="undergraduate"switcheducation{case"doctor":fmt.Println("我是医生")case"graduatestudent":fmt.Println("我是研究生")case"undergraduate":fmt.Println("我是本科生")case"College":fmt.Println("我是大学生")default:fmt.Println("学历不达标..")}}4。使用可变参数*args第二种情况和第三种情况很相似,不同的是第三种情况在users前加了一个*,和原来Python函数中的可变参数一样,会匹配多个列表的值。这意味着可以通过命令行参数批量创建用户。如果match-case中对应的case运行了,就会创建对应的变量。例如:5.使用可变参数**kv在下面的代码中,**rest会匹配args6中的所有key和value。长度匹配如果你只想用case对对象的长度做一些匹配,你可以使用类似[*_]的东西来匹配任意长度的列表;(,,*_)来匹配一个长度至少为2的元组。7.类对象的匹配对于类对象的匹配,下面的例子很简单,这里不再赘述。8、注意搭配顺序。match-case的使用上面已经基本介绍过了。如果您需要更详细的内容,最好阅读PEP636(https://www.python.org/dev/peps/pep-0636/)的内容。在文章的开头,我说过开发者应该对这些新特性感到敬畏。像match-case这样看似简单的新特性,学习成本却很高。如果对结构模式匹配一??知半解的人,可能会增加代码错误的概率,这不是一般人可以轻易控制的。之所以这样说,是因为match-case面对的对象不同,其匹配规则也不同。当匹配的对象是列表或元组时,长度和元素值都必须匹配才能命中,这就是为什么下面的例子使用第三种情况而不是第二种情况。当匹配对象是dict时,规则不同,只要匹配对象中存在case表达式中的key,就可以命中。当match的对象是类对象时,匹配规则有点类似于dict,只要对象类型和对象的属性满足case的条件,就可以命中。所以,在写match-case的时候,最大的难点可能就是如何把握这个顺序,保证自己写的代码不会推翻。我个人总结了一些规则,仅供大家参考:listortuple:shouldneverbeformattingtostrictdictorobject:shouldbefromstricttonotstrict经过半天的尝鲜,自己有了一些理解,分享给大家你,不知道我的理解有没有问题,但是还是建议大家在充分理解match-case的匹配规则之后再使用。
