当前位置: 首页 > 科技观察

为什么Python不支持switch语句?

时间:2023-03-13 23:59:12 科技观察

在这篇文章中,我们将讨论为什么Python决定不支持switch语句。为什么要聊这个话题?主要原因是switch在其他语言中太常见了,Python却不支持。这样的独特性值得关注,回答这个问题也能清楚地看到Python在编程概念上,理解Python在语法设计上的决策过程。本文除了详细分析PEP-275和PEP-3103之外,还将介绍Python(PEP-622)的最新进展,即可能引入的模式匹配语法。我相信这个话题会开阔你的视野。从而对switch语法有一个更全面的了解。1、什么是开关?在开始正题之前,我们需要先说一下什么是switch?有的同学可能是第一次想到。。。嘿嘿~,请放轻松,别老想着游戏,我们要说的是编程语言中的switch语句。一般来说,switch的语法格式如下:switch(expression){casevalue1://statementbreak;//optionalcasevalue2://statementbreak;//optionaldefault://optional//statement}使用流程图吧大致是这样的:它的用法不难理解:switch语句的值满足哪种case,就会执行相应的代码块,执行中遇到break就跳出,否则继续执行下一个案件分支;一般最后会放一个defaultbranch作为backstop。大多数语言都提供了switch语句或者非常类似的东西,比如在C/C++/Java/Go等静态语言中,都支持switch-case结构;在Ruby中有类似的case-when结构,在Shell语言中,有类似的case-in结构。在Perl中,有switch-case-else...switch语句的优点是支持“单条件多分支”的选择结构。相比if-else的二元选择结构,in有时会更加简洁明了。然而,在Python中,我们看不到switch-case或类似的语法结构。为什么?2、为什么Python不支持switch?官方文档中有一个FAQ,里面有这样一个问题:Whyisn'tthereaswitchorcasestatementinPython?FAQ是FrequentlyAskedQuestions的缩写,意思是经常被问到的问题。官方27个常见问题列表在这里:https://mp.weixin.qq.com/s/zabIvt4dfu_rf7SmGZXqXg这个文档给出了几个建议,告诉了我们几个switch/case的备选方案:使用if-elif-else条件判断语句使用字典将case值映射到被调用的函数使用内置的getattr()检索特定对象被调用的方法已经有提案(即PEP-275和PEP-3103)将switch语法引入Python,但是,对于是否以及如何进行范围测试还没有达成共识。射程试验,即射程试验,是指对武器弹药技术性能进行的各种试验和验证。就像药物的临床试验一样,它是最终产品交付前的关键测试。官方文档对“为什么Python不引入switch”的解释其实来自于Python之父GuidovanRossum在PEP-3103中的观点:来源:https://www.python.org/dev/peps/pep-3103我在PyCon2007的主题演讲中进行的一项快速投票显示,该提案没有得到普遍支持。因此我拒绝它。因此,我拒绝了。简而言之,有一个PEP提案和一个基本的语法实现,但核心开发人员似乎未能达成共识,最终导致该提案流产。3.PEP-275和PEP-3103说了什么?PEP-3103是2006年提出的,PEP-275是2001年提出的,它们的共同点是需要引入switch语句,分析了几种替代实现方式,但是都被否决了。来源:https://www.python.org/dev/peps/pep-0275那么,我们先来回顾一下核心开发者都做了哪些讨论,看看Python要实现switch结构,会是怎样的呢?(PS:PEP还涉及其他内容,本文只摘录与switch直接相关的部分)PEP-275提出的语法结构如下:switchEXPR:caseCONSTANT:SUITEcaseCONSTANT:SUITE...else:SUITEwhereelsebranchisoptional没有它什么也不做,前面的分支都不满意。此外,case值常量支持不同的类型,因为expr表达式的类型是动态的。PEP-275还提出switch不支持fall-through行为,即每个case分支都是独立完整的,不需要像C语言那样写break。PEP还列出了一些其他问题:复用现有关键字,不要引入“switch”和“case”使用新关键字,避免与C的switch概念混淆支持单分支多值选择(例如:case'a','b','c':…)还有支持范围值判断的建议(例如:case10..14:…)除了首选方案,本PEP还记录了几种不同风格的语法方案:caseEXPR:ofCONSTANT:SUITEofCONSTANT:SUITEelse:SUITEcaseEXPR:ifCONSTANT:SUITEifCONSTANT:SUITEelse:SUITEwhenEXPR:inCONSTANT_TUPLE:SUITEinCONSTANT_TUPLE:SUITE...else:SUITEPEP-275记录了很多重要的思想和问题,对PEP-3103的出现做出了很大的贡献.好伏笔。那么,让我们来看看Guido编写的PEP-3103是怎么说的。它首先识别PEP-275中的两个基本设置,比如实现“隐式break”,防止case分支中fall-through等控制权的转移(其他语言好像需要显式写break);else分支是可选的,重用else关键字而不引入“default”。Guido认同PEP-275所提倡的风格,但他也认为它的问题在于缩进层级过多。因此,建议减少代码分支缩进的空格数。比如原来的缩进是4个空格,缩进是2个空格。PEP-3103还列出了其他三种实现方案,并分析了它们的区别和问题。具体内容从略。这里我们只展示它们的样式:#case分支不缩进switchEXPR:caseEXPR:SUITEcaseEXPR:SUITE....else:SUITE#switch语句后没有冒号switchEXPRcaseEXPR:SUITEcaseEXPR:SUITE....else:SUITE#省略case关键字switchEXPR:EXPR:SUITEEXPR:SUITE...else:SUITE在基本语法之外,GuidoHua大量篇幅专门讨论扩展语法(ExtendedSyntax),即匹配多个值的复杂情况在case分支中:caseEXPR,EXPR,...:#GuidopreferredcaseinEXPR_LIST:case*EXPR:case[*]EXPR,[*]EXPR,...:case*(EXPR,EXPR,...):他考虑的关键问题包括:switch中表达式的结果是元组或可迭代对象,case的值是作为元组拆包的case,在case分支做“*”星号操作...然后,Guido花了很多篇幅来分析switch是如何实现的。其中讨论的主要思想是:使用等价的if-elif链来定义switch语句(可能会做一些优化)同上,所有表达式必须是可散列的(hashable)见预计算字典的调度(dispatch)这部分PEP有很多,因为Guido也为每个idea考虑了几种实现路径,这导致他经过复杂的分析后得出结论:Itistooearlytodecision(现在决定还为时过早)。看完PEP-3103,我的总体感觉是Guido的思维发散性很强,层次丰富,但缺乏面对其他问题时的“尖刀”洞察力。也就是说,在众多可能的解决方案中,他想尽办法涵盖了方方面面,但最终还是无法说服自己做出独裁的决定。阻力主要来自于自己,而不是来自他人。不过,造成这种情况的原因可能与他预设的立场有关:他似乎认为“Python没有switch语句也可以”,所以虽然他写了很长的PEP,但他只是把问题复杂化,把话题搁置了.最后,他对PyCon进行了小范围的调查,以至于“理直气壮”地拒绝了他发起的PEP,试图堵住大家的嘴……4.以后会有switch语句吗?总之,Python没有switch语句的原因。原因是:switch的实现细节/功能点还没有敲定,没有switch就好,switch还有其他好的替代方法,还有Guido的小任性……不过,我们还是要问:会发生什么将来?有switch语句吗?或者类似的多分支选择结构?你为什么要问?原因是有switch语句的语言太多了,很多人尝试写提供switch功能的库(我记得在PyCoder的Weekly上看过两遍)。我(Python猫)不喜欢从头到尾切换。几乎可以肯定的是,Python以后不会有switch,但是很可能会引入类似switch的更复杂的语法结构!2020年6月,PEP-622提出,提出在Scala、Erlang、Rust等语言中引入模式匹配。截至2020年10月,该PEP已分解为另外三个PEP(634-636),目前均处于草案阶段。考虑到核心开发者的参与和话题的讨论,这些提议很有可能会在未来的版本中实现(比如正在开发的3.10)。以average函数为例,模式匹配语法可以这样实现:defaverage(*args):matchargs:case[x,y]:#capturestthetwoelementsofasequencereturn(x+y)/2case[x]:#capturestheonlyelementofasequencereturnxcase[]:return0casex:#capturestheentiresequencereturnsum(x)/len(x)match-case结构类似于switch-case结构,但它是基于模式(pattern)而不是表达式(expression),所以有更多的细节有待考虑,还有更广阔的应用空间。建议对此主题感兴趣的读者查看这些新的PEP。最后,我们回到标题中的问题:为什么Python不支持switch语句?官方文档的FAQ对这个问题有回答,告诉我们有几个不错的替代方案,还留下了一个线索:曾经有一个PEP提出要引入一个switch,但是没有成功实现。顺着这个线索,本文对PEP-275和PEP-3103这两个文档进行了拆解,向大家展示了Python社区中提出的不同风格的switch解决方案,以及很多未解决的问题。最后,我们还关注了PEP-622的最新进展。看来switch这个“孪生兄弟”匹配语法有望引入Python!switch话题的讨论似乎要终止了,但另一个更大的话题正在进行中!作者简介猫下豌豆花,广东人,毕业于武汉大学,现为苏飘程序员。他有一些极客思维,有一些人文情怀,有温度,有态度。本文转载自微信公众号“蟒猫”,可通过以下二维码关注。转载本文请联系Python猫公众号。