当前位置: 首页 > 后端技术 > Python

Python3.10正式发布,新增模式匹配,同事用着说真香!

时间:2023-03-26 16:04:38 Python

关注微信公众号:爬虫K哥,QQ交流群:808574309,持续分享爬虫进阶、JS/Android逆向等技术干货!前几天,10月4日,Python发布了3.10.0版本,什么?3.9之后就不是4.0了吗?(手动狗头)其实龟叔(Python之父GuidovanRossum)早在去年9月份就说过:3.9之后的版本是3.10;事实上,它已经存在(在master分支的GithubMaster中)。如果有版本4,从3到4的过渡更像是从1到2而不是从2到3。与Python3.9相比,Python3.10的主要新特性如下:PEP634-PEP636:结构模式匹配在本次的众多更新中,结构模式匹配和match-case语句无疑是最令人兴奋的特性。类似于Java、C、Go等语言中的switch-case语句。具体用法可以参考:PEP636看一个简单的例子:defhttp_error(status):matchstatus:case400:print("Badrequest")case404:print("Notfound")case418:print("I'mateapot")case_:print("Something'swrongwiththeinternet")http_error(418)#I'mateapothttp_error(500)#Something'swrongwiththeinternet在上面的代码中,最后一个_case不作为变量名使用,而是代表一种特殊的模式。在前面的case中miss的情况下,这个case会是最后的保证,可以保证命中,相当于Java、C、Go等语言中的默认分支:publicclassHttpError{publicstaticvoidmain(字符串args[]){int状态=500;开关(状态){案例400:系统。out.println("错误请求");case404:System.out.println("Notfound");case418:System.out.println("I'mateapot");efault:System.out.println("网络有问题");}}}//internetmatch-case语法有问题支持可变参数*args和**rest*args的用法与Python函数中的可变参数相同,允许传入多个参数:defcreate_user(command):matchcommand.split():case["quit"]:quit()case["create",user]:print("create",user)case["create",*user]:foruinuser:print("create",u)case_:print("command'{command}'不是明白了")create_user("createuser1")create_user("createuser2user3user4")#createuser1#createuser2#createuser3#createuser4**rest会匹配字典中所有的key和value:defget_dict(dic):matchdic:case{**rest}:print("getdict:",rest)case_:print("参数不理解")get_dict({"400":"错误请求","404":"Notfound","418":"I'mateapot"})#getdict:{'400':'Badrequest','404':'Notfound','418':"I'mateapot"}需要注意的是,结构模式匹配面对不同对象时,匹配规则也不同。当匹配对象是列表(list)或元组(tuple)时,长度和元素值都必须匹配才能命中:defcreate_user(param):matchparam:case("quit"):quit()case("create",user):print("create",user)case("create",*user):foruinuser:print("create",u)案例_:print("command'{command}'不懂")create_user(("create","user1","user2"))#createuser1#createuser2当匹配的对象是字典(dict)时,只要case表达式中的键(key)是在字典对象下面的例子中,很可能会执行第二种情况,但实际执行的是第一种情况:defif_action(dic):matchdic:case{"action":action}:print("action:%s,noobject"%action)case{"action":action,"object":_}:print("action:%s,haveobject"%action)if_action({"action":"create","object":"user1"})#action:create,noobject当匹配对象为类对象(class)时,匹配规则类似于字典(dict),只要对象类型和对象属性满足条件就可以命中。在下面的示例中,很可能会执行第二种情况,但实际上会执行第一种情况:classInfo:def__init__(self,name,age):self.name,self.age=name,agedefget_info(people):匹配人:caseInfo(name="Bob"):print("case1")caseInfo(name="Bob",age="20"):print("case2")people=Info(name="Bob",age="20")get_info(people)#case1PEP604:新联合运算符(联合类型)Python是一种弱类型语言,但在Python3支持定义参数传递和返回类型的写法:deftest(a:int)->int:returna**2通常一个参数和返回值只能是一种类型,在C/C++、Java、Go和其他static语言中,不可能返回两种类型,或者使用两种类型的参数,但是在Python中是可以的:deftest(a:strorint)->strorint:returna**2的或者这里的写法看起来很不舒服,所以Python3.5引入了typing模块,推荐使用Uinon:fromtypingimportUniondeftest(a:Union[str,int])->Union[str,int]:returna**2在这次Python3.10.0更新中,PEP604允许联合类型(UnionTypes)写成X|Y:deftest(a:str|int)->str|int:returna**2newoperators也可以作为isinstance()和issubclass()的第二个参数:print(isinstance(5,int|str))#Trueprint(isinstance(None,int|None))#Trueprint(issubclass(bool,int|float))#Trueprint(isinstance(42,N一个|str))#FalsePEP626:错误调试精确到行在PEP626中,错误提示可以精确到具体行,提示更详细。在以前的版本中,错误消息通常指向下一行而不是实际的错误。现在您可以指向错误代码的确切位置。错误代码示例1:li=[1,2,3之前的版本报错:File"D:\python3Project\test.py",line5^SyntaxError:unexpectedEOFwhileparsingPythonVersion3.10报错:File"D:\python310Project\test.py",line4li=[1,2,3^SyntaxError:'['wasneverclosed错误代码示例2:expected={"name":"Bob","age":20Some_other_code=foo()之前版本报错:File"D:\python3Project\test.py",line2some_other_code=foo()^SyntaxError:invalidsyntaxPython3.10版本报错:File"D:\python310Project\test.py",line1expected={"name":"Bob","age":20^SyntaxError:'{'wasneverclosedPEP618:zip()的可选长度检查zip()是一个内置函数Python用于将一个可迭代对象作为参数,将对象中对应的元素打包成元组,然后返回由这些元组组成的列表。在之前的版本中,如果每个迭代器的元素个数不一致,则返回的list长度与最短对象相同,例子如下:a=[1,2,3]b=[4,5,6]c=[4,5,6,7,8]zipped1=zip(a,b)zipped2=zip(a,c)#元素个数与最短列表相同print([zforzinzipped1])#[(1,4),(2,5),(3,6)]print([zforzinzipped2])#[(1,4),(2,5),(3,6)]在PEP618中,添加了一个新的严格参数。当设置为True时,传递给zip()的两个可迭代项的长度必须相等,否则ValueError=[1,2,3]b=[4,5,6]c=[4,5,6,7,8]zipped1=zip(a,b,strict=True)zipped2=zip(a,c,strict=True)print([zforzinzipped1])print([zforzinzipped2])错误:[(1,4),(2,5),(3,6)]Traceback(最近调用last):文件“D:\python310Project\test.py”,第8行,在print([zforzinzipped2])File"D:\python310Project\test.py",line8,inprint([zforzinzipped2])ValueError:zip()argument2islongerthanargument1BPO-12782:Allow带括号的上下文管理器Python上下文管理器对于打开/关闭文件、处理数据库连接和许多其他事情非常有用,并且在Python3.10.0中它们的语法将有一点质量BPO-12782中的改进正式允许带括号的上下文管理器,现在可以用一个with语句创建多行,例如:with(open("text1.txt",encoding="utf-8")asf1,open("text2.txt",encoding="utf-8")asf2):打印(f1.read(),f2.read())PEP613:ExplicittypealiasesPEP613使用TypeAlias显式注解类型别名以提高可读性以前的版本,如你所见,x很容易混淆:x=intdefplus_int(a:x,b:x)->x:returna+b在Python3.10中,使用TypeAlias表示这是一个别名以消除歧义:fromtypingimportTypeAliasx:TypeAlias=intdefplus_int(a:x,b:x)->x:returna+b性能改进与所有最新版本的Python一样,Python3.10带来了一些性能改进。首先是优化了str()、bytes()和bytearray()构造函数,它们的速度提高了大约30%。代码取自BOP-41334:$./python-mpyperftimeit-q--compare-to=../cpython-release2/python"str()"Mean+-stddev:[/home/serhiy/py/cpython-release2/python]81.9ns+-4.5ns->[/home/serhiy/py/cpython-release/python]60.0ns+-1.9ns:快1.36倍(-27%)$./python-mpyperftimeit-q--compare-to=../cpython-release2/python"bytes()"Mean+-stddev:[/home/serhiy/py/cpython-release2/python]85.1ns+-2.2ns->[/home/serhiy/py/cpython-release/python]60.2ns+-2.3ns:快1.41倍(-29%)$./python-mpyperftimeit-q--compare-to=../cpython-release2/python"bytearray()"Mean+-stddev:[/home/serhiy/py/cpython-release2/python]93.5ns+-2.1ns->[/home/serhiy/py/cpython-release/python]73.1ns+-1.8ns:1.28xfaster(-22%)另一个更值得注意的优化(如果你使用类型注解),函数参数及其注解不再在运行时(runtime)计算,而是在编译时计算,这使得创建一个带有参数的函数注释速度大约快2倍。除此之外,Python核心的各个部分还有更多优化,您可以在Python错误跟踪器的以下问题中找到更多详细信息:BPO-41718、BPO-42927、BPO-43452。其他更改PEP623:已弃用并准备删除PyUnicodeObject中的wstr成员。PEP612:参数规范变量。PEP632:弃用distutils模块以支持setuptools。PEP644:CPython的标准库仅支持OpenSSL1.1.1或更新版本。PEP624:删除Py_UNICODE编码器API。PEP597:添加可选的编码警告。