Python 为什么不支持 switch 语句?-Python教程

资源魔 24 0
正在Python教程栏目这篇文章里,咱们会聊一聊为何 Python 决议没有支持 switch 语句。

为何想要聊这个话题呢?

次要是由于 switch 正在其它言语中太常见了,而 Python 却没有支持,这样的共同性自身就值患上存眷,而答复这个成绩,也能愈加看清 Python 正在顺序设计上的理念,理解 Python 正在语法设计中的决议计划进程。

本文除了了会具体剖析 PEP-275 以及 PEP-3103,还会引见到 Python 最新的倒退静态(PEP-622),便可能要引入的模式婚配(pattern matching)语法,置信这个话题会宽阔各人的眼界,从而对 switch 语法有更为片面的意识。

一、switch 是甚么?

正在开端正题以前,咱们需求先聊聊 switch 是甚么?

有些同窗可能会第一工夫想到它……

喂~喂~,费事收收心,别总想着游戏啦,咱们要说的是编程言语中的 switch 语句。

普通而言,switch 的语法格局以下:

switch(expression){    case value1:       // 语句
       break; // 可选
    case value2:       // 语句
       break; // 可选
    default: // 可选
       // 语句}复制代码

应用流程图来示意,大略是这样的:

它的用法没有难了解:switch 语句的值餍足哪个 case 状况,就会执行对应的代码块,执行时遇到 break 就跳出,不然就持续执行下一个 case 分支;普通会正在最初放一个 default 分支,作为兜底。

年夜少数言语都提供了 switch 语句或许极端类似的货色,例如,正在 C/C++/Java /Go 等动态言语中,它们都支持 switch-case 构造;正在 Ruby 中有相似的 case-when 构造,正在 Shell 言语中,有类似的 case-in 构造,正在 Perl 中,有 switch-case-else……

switch 语句的益处是支持“单前提多分支”的抉择构造,相比 if-else 的二分抉择构造,正在某些时分会更为简约明晰。

然而,正在 Python 中,咱们看没有到 switch-case 或许相近的语法构造,这是为何呢?

二、Python 为何没有支持 switch?

民间文档中有一篇 FAQ 蕴含了这个成绩:Why isn’t there a switch or case statement in Python?

FAQ 即 Frequently Asked Questions 的缩写,示意常见成绩,民间列了 27 个常见成绩,完好清单正在此:mp.weixin.qq.com/s/zabIvt4df…

该文档给出了几个倡议,通知了咱们几个 switch/case 的代替计划:

  • 应用 if-elif-else 前提判别语句
  • 应用字典,将 case 值与挪用的函数映照起来
  • 应用内置 getattr() 检索特定的工具挪用办法

曾有人提出过一些提案(即 PEP-275 以及 PEP-3103),想给 Python 引入 switch 语法,但是,关于“能否和若何进行靶场测试”,各人不告竣分歧的共鸣。

靶场测试,即 range test,指的是对武器弹药的技巧功能作各类测实验证,与药物的临床实验同样,都是正在终极产物交付前的一项要害性测试。

民间文档关于“为何 Python 没有引入 switch”的诠释,实际下去源于 Python 之父 Guido van Rossum 正在 PEP-3103 中的定见:

出处:www.python.org/dev/peps/pe…

A quick poll during my keynote presentation at PyCon 2007 shows this proposal has no popular support. I therefore reject it.

我正在 PyCon 2007 的主题演讲中做了一个疾速的民心考察,后果标明这个提案不失去宽泛的支持。因而,我回绝了它。

简而言之,PEP 提案有了,语法完成也有了雏形,然而外围开发者们仿佛不告竣分歧定见,终极招致提案流产了。

三、PEP-275 与 PEP-3103 说了甚么?

PEP-3103 是正在 2006 年提出的,PEP-275 则是正在 2001 年提出的,它们的独特的地方是提出了引入 switch 语句的某种须要性、剖析了好几种备选的完成计划,但是,终局是都被回绝了。

出处:www.python.org/dev/peps/pe…

那末,咱们就先来回顾一下外围开发者们都做出了哪些探讨,看一看假如 Python 要完成 switch 构造,会是怎样样子的?(PS:PEP 里还触及其它内容,本文只摘取与 switch 间接相干的局部)

PEP-275 提出的语法构造以下:

switch EXPR:
    case CONSTANT:
        SUITE
    case CONSTANT:
        SUITE
    ...    else:
        SUITE复制代码

此中 else 分支是可选的,假如不它,而且后面的分支都没有餍足的话,就甚么也没有做。另外 case 值 constant 支持没有同类型,由于 expr 表白式的类型是静态的。

PEP-275 还提出让 switch 没有支持掉落(fall-through)行为,即每一个 case 分支互相自力而完好,不必像 C 言语那样需求写 break。

该 PEP 还罗列了一些其它的 issue:

  • 重用现无关键字,没有引入“switch”以及“case”
  • 应用新的要害字,防止与 C 的 switch 概念混杂
  • 支持单分支多值抉择(例如:case 'a', 'b', 'c': ...)
  • 另有倡议支持范畴取值判别(例如:case 10..14: ...)

除了了首选计划,该 PEP 还记载了几种格调各别的语法计划:

case EXPR:
    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复制代码

PEP-275 记载下了很多首要的思绪以及成绩,为 PEP-3103 的呈现做了很好的铺垫。

那末,咱们再来看看由 Guido 编写的 PEP-3103 说了些甚么吧。

它起首认可了 PEP-275 中的两个根底设定,例如,完成“隐式的 break”,没有让 case 分收入现 fall-through 这类转移管制权的状况(其它言语仿佛都要求显式地写 break);else 分支是可选的,复用 else 要害字,而不必引入“default”。

关于 PEP-275 倡导的那种格调,Guido 比拟认可,但也以为它的成绩是缩进条理太多,因而倡议缩小代码分支缩进的空格数,例如原本缩进 4 空格,改成缩进 2 空格。

PEP-3103 还罗列了另外三种完成计划,剖析了它们的差别和成绩,详细内容从略,这里只给各人看看它们的格调:

# case 分支没有缩进switch EXPR:
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复制代码

正在根底语法以外,Guido 花了不少篇幅来探讨扩大语法(Extended Syntax),即正在一个 case 分支中完成婚配多个值的复杂状况:

case EXPR, EXPR, ...:# Guido 优选的case in EXPR_LIST:

case *EXPR:

case [*]EXPR, [*]EXPR, ...:

case *(EXPR, EXPR, ...):复制代码

他重点思考到的成绩包罗:switch 中表白式的后果是元组或可迭代工具的状况、case 的值被算作元组解包的状况、正在 case 分支作“*”星号操作……

接着,Guido 又用了十分十分多的篇幅来剖析该若何完成 switch,此中探讨到的次要思绪有:

  • 应用等价的 if-elif 链来界说 switch 语句(可能会做些优化)
  • 同上,另外一切表白式都必需是可哈希的(hashable)
  • 看做是事后较量争论的字典的分拨(dispatch)

PEP 中这局部的内容十分多,由于正在每一个思绪上,Guido 还思考到了好几种完成门路,这招致了他正在复杂剖析后的论断是:It is too early to decide( 如今做决议为时髦早)。

浏览完 PEP-3103 后,我总体的觉得是:Guido 的思绪十分发散、条理丰厚,然而,短少了他正在面临其它成绩时那“一刀两断”式的洞察力。

也就是说,正在诸多的可能性计划中,他力图八面玲珑,终极无奈压服本人做出一个独裁的决议。阻力次要来自于他本人,而没有是其余人。

不外,之以是会呈现这类状况,兴许跟他的预设态度无关:他仿佛以为“Python is fine without a switch statement”,因而虽然写了很长的 PEP,但只是正在把成绩复杂化,把议题放置起来。

最初,他正在 PyCon 上做了一个小范畴考察,借此“理直气壮”地回绝了本人发动的 PEP,试图堵住世人的悠悠之口……

四、将来会有 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 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)复制代码

match-case 构造神似于 switch-case 构造,但是它基于模式(pattern)而非表白式(expression),因而有更多待思考的细节成绩,也有更为广阔的使用空间。

对此话题感兴味的读者,倡议去查阅这几个新的 PEP。

最初,让咱们回到题目中的成绩:Python 为何没有支持 switch 语句?

民间文档的 FAQ 对此成绩有一个解答,通知咱们有几个没有错的代替写法,同时也留下了一条线索:曾有 PEP 提议引入 switch,只是不胜利完成。

沿着这条线索,本文拆解了 PEP-275 以及 PEP-3103 这两篇文档,带各人看到了 Python 社区里提出过的格调各别的 switch 计划,和诸多的悬而未决的成绩。

最初,咱们还存眷到了最新的 PEP-622 的静态,看起来 switch 的“孪生兄弟” match 语法无望引入到 Python 中!switch 话题的探讨仿佛要终止了,然而另外一个更年夜的话题在进行中!

相干收费学习保举:python教程(视频)

以上就是Python 为何没有支持 switch 语句?的具体内容,更多请存眷资源魔其它相干文章!

标签: Python python教程 python编程 python使用问题 switch

抱歉,评论功能暂时关闭!