python没有switch,python中switch的用法
在Python教程专栏的这篇文章中,我们将讨论Python为什么决定不支持switch语句。
为什么要谈这个话题?
主要是因为switch在其他语言中太常见了,Python却不支持,其独特性本身就值得关注。回答这个问题也可以帮助你看到Python在编程上的思路,了解Python在语法设计上的决策过程。
本文不仅会详细分析PEP-275和PEP-3103,还会介绍Python (PEP-622)的最新发展,即可能引入的模式匹配文法。相信这个话题会开阔我们的眼界,对开关语法有更全面的了解。
00-1010在进入正题之前,我们需要先说一下switch是什么?
有些学生可能第一时间就想到了.
你好~你好~,请小心,不要总想着游戏,我们说的是编程语言中的switch语句。
一般来说,switch的语法格式如下:
switch(expression){ case value 1://语句
打破;//可选
值2://语句
打破;//可选
默认3360//可选
//statement}复制代码由一个流程图表示,大概是这样的:
它的用法不难理解:switch语句的值满足哪种情况,就会执行对应的代码块,遇到断点就会跳出,否则继续执行下一个case分支;一般来说,默认的分支会放在最后作为底部。
大多数语言都提供switch语句或类似的东西。比如在C/C /Java /Go等静态语言中,都支持switch-case结构;Ruby中有类似的case-when结构,Shell语言中有类似的case-in结构,Perl中有switch-case-else……结构.
switch语句的优点是支持“单条件多分支”选择结构。相比if-else的二元选择结构,在某些情况下会更加简洁明了。
然而,在Python中,我们看不到switch-case或类似的语法结构。为什么?
00-1010官方文档中有一个FAQ包含了这个问题:为什么Python中没有switch或者case语句?
FAQ代表常见问题,它代表常见问题。27个常见问题的官方列表在这里:mp.weixin.qq.com/s/zabIvt4df…
本文档给出了一些建议,并告诉我们开关/外壳的几种替代方案:
使用if-elif-else条件判断语句将case值映射到被调用的函数,并使用内置的getattr()检索具体的对象调用方法。已经提出了一些建议(即PEP-275和PEP-3103)来将开关语法引入Python。然而,在"是否以及如何进行靶场测试"问题上还没有达成共识。
靶场试验,即靶场试验,是指验证武器弹药技术性能的各种试验。就像药物的临床试验一样,它是最终产品交付前的关键测试。
文档中“Python为什么不引入switch”的官方解释,其实来自于“Python之父”吉多范罗苏姆在PEP-3103中的观点:
来源:www.python.org/dev/peps/pe…
我在2007年PyCon大会上发表主题演讲时的一项快速民意调查显示,这一提议没有得到广泛支持。因此,我拒绝它。
我在PyCon 2007的主题演讲中做了一个快速的民意调查,结果显示这个建议并没有得到广泛的支持。所以,我拒绝了。
简而言之,PEP 提案有了,语法实现也有了雏形,但是核心开发者们似乎没有达成一致意见,最终导致提案流产了。
00-1010PEP-3103是2006年提出的,而PEP-275是2001年提出的。它们的共同点是引入了switc。
h 语句的某种必要性、分析了好几种备选的实现方案,然而,结局是都被拒绝了。
出处:www.python.org/dev/peps/pe…
那么,我们就先来回顾一下核心开发者们都做出了哪些讨论,看一看如果 Python 要实现 switch 结构,会是怎么样子的?(PS:PEP 里还涉及其它内容,本文只摘取与 switch 直接相关的部分)
PEP-275 提出的语法结构如下:
switch EXPR:其中 else 分支是可选的,如果没有它,并且前面的分支都不满足的话,就什么也不做。另外 case 值 constant 支持不同类型,因为 expr 表达式的类型是动态的。case CONSTANT:
SUITE
case CONSTANT:
SUITE
... else:
SUITE复制代码
PEP-275 还提出让 switch 不支持掉落(fall-through)行为,即每个 case 分支相互独立而完整,不用像 C 语言那样需要写 break。
该 PEP 还列举了一些其它的 issue:
- 重用现有关键字,不引入“switch”和“case”
- 使用新的关键字,避免与 C 的 switch 概念混淆
- 支持单分支多值选择(例如:case 'a', 'b', 'c': ...)
- 还有建议支持范围取值判断(例如:case 10..14: ...)
case EXPR:PEP-275 记录下了不少重要的思路和问题,为 PEP-3103 的出现做了很好的铺垫。of CONSTANT:
SUITE
of CONSTANT:
SUITE else:
SUITE
case EXPR: if CONSTANT:
SUITE if CONSTANT:
SUITE else:
SUITE
when EXPR: in CONSTANT_TUPLE:
SUITE in CONSTANT_TUPLE:
SUITE
...else:
SUITE复制代码
那么,我们再来看看由 Guido 编写的 PEP-3103 说了些什么吧。
它首先认可了 PEP-275 中的两个基础设定,例如,实现“隐式的 break”,不让 case 分支出现 fall-through 这种转移控制权的情况(其它语言似乎都要求显式地写 break);else 分支是可选的,复用 else 关键字,而不用引入“default”。
对于 PEP-275 提倡的那种风格,Guido 比较认可,但也认为它的问题是缩进层次太多,因此建议减少代码分支缩进的空格数,例如本来缩进 4 空格,改为缩进 2 空格。
PEP-3103 还列举了另外三种实现方案,分析了它们的差异以及问题,具体内容从略,这里只给大家看看它们的风格:
# case 分支不缩进switch EXPR:在基础语法之外,Guido 花了很多篇幅来讨论扩展语法(Extended Syntax),即在一个 case 分支中实现匹配多个值的复杂情况:case EXPR:
SUITE
case EXPR:
SUITE
....else:
SUITE# switch 语句后不加冒号switch EXPR
case EXPR:
SUITE
case EXPR:
SUITE
....else:
SUITE# 省略 case 关键字switch EXPR:
EXPR:
SUITE
EXPR:
SUITE
... else:
SUITE复制代码
case EXPR, EXPR, ...:# Guido 优选的case in EXPR_LIST:他重点考虑到的问题包括:switch 中表达式的结果是元组或可迭代对象的情况、case 的值被看成元组解包的情况、在 case 分支作“*”星号操作……case *EXPR:
case [*]EXPR, [*]EXPR, ...:
case *(EXPR, EXPR, ...):复制代码
接着,Guido 又用了非常非常多的篇幅来分析该如何实现 switch,其中讨论到的主要思路有:
- 使用等价的 if-elif 链来定义 switch 语句(可能会做些优化)
- 同上,另外所有表达式都必须是可哈希的(hashable)
- 看作是预先计算的字典的分派(dispatch)
阅读完 PEP-3103 后,我总体的感觉是:Guido 的思路非常发散、层次丰富,但是,缺少了他在面对其它问题时那“快刀斩乱麻”式的洞察力。
也就是说,在诸多的可能性方案中,他力求面面俱到,最终无法说服自己做出一个独裁的决定。阻力主要来自于他自己,而不是其他人。
不过,之所以会出现这种情况,也许跟他的预设立场有关:他似乎认为“Python is fine without a switch statement”,因此尽管写了很长的 PEP,但只是在把问题复杂化,把议题搁置起来。
最后,他在 PyCon 上做了一个小范围调查,借此“名正言顺”地拒绝了自己发起的 PEP,试图堵住众人的悠悠之口……
4、未来会有 switch 语句么?
归结起来,之所以 Python 没有 switch 语句,原因有:switch 的实现细节/功能点未经敲定、没有 switch 也挺好的、有其它不错的方法替代 switch、Guido 的小任性……但是,我们还是要追问一句:未来会有 switch 语句么?或者类似的多分支选择结构?
为什么要有此一问呢?原因是有太多语言自带 switch 语句,而且也有很多人尝试编写提供 switch 功能的库(我记得在 PyCoder's Weekly 里曾见到过两次)。
我(Python猫)本人自始至终并不喜欢 switch,几乎可以肯定地说,Python 未来也不会有 switch,但是,它很可能会引入一个类似于 switch 且更为复杂的语法结构!
2020 年 6 月,PEP-622 被提出了,它建议引入在 Scala、Erlang 和 Rust 等语言中的模式匹配语法(pattern matching)。
截至 2020 年 10 月,该 PEP 已被分解成另外三个 PEP(634-636),目前都处于草案阶段。考虑到核心开发者们的参与情况以及话题讨论的情况,这些提案极有可能会在未来版本(比如正在开发中的 3.10)中实现。
以一个求平均数的函数为例,模式匹配语法可以实现成这样:
def average(*args):match-case 结构神似于 switch-case 结构,然而它基于模式(pattern)而非表达式(expression),因此有更多待考虑的细节问题,也有更为广阔的应用空间。match args:
case [x, y]: # captures the two elements of a sequence
return (x + y) / 2
case [x]: # captures the only element of a sequence
return x
case []: return 0
case x: # captures the entire sequence
return sum(x) / len(x)复制代码
对此话题感兴趣的读者,建议去查阅这几个新的 PEP。
最后,让我们回到标题中的问题:Python 为什么不支持 switch 语句?
官方文档的 FAQ 对此问题有一个解答,告诉我们有几个不错的替代写法,同时也留下了一条线索:曾有 PEP 提议引入 switch,只是没有成功实现。
沿着这条线索,本文拆解了 PEP-275 和 PEP-3103 这两篇文档,带大家看到了 Python 社区里提出过的风格各异的 switch 方案,以及诸多的悬而未决的问题。
最后,我们还关注到了最新的 PEP-622 的动态,看起来 switch 的“孪生兄弟” match 语法有望引入到 Python 中!switch 话题的讨论似乎要终止了,但是另一个更大的话题正在进行中!
相关免费学习推荐:python教程(视频)以上就是Python 为什么不支持 switch 语句?的详细内容,更多请关注盛行IT软件开发工作室其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。