关于python:Python-为什么不设计-dowhile-循环结构

6次阅读

共计 2834 个字符,预计需要花费 8 分钟才能阅读完成。

在某些编程语言中,例如 C/C++、C#、PHP、Java、JavaScript 等等,do-while 是一种根本的循环构造。

它的外围语义是:先执行一遍 循环体代码 ,而后执行一遍 条件语句,若条件语句判断为真,则继续执行循环体代码,并再次执行条件语句;直到条件语句判断为假,则跳出循环构造。

流程图如下(Java 示例):

// 打印小于 20 的数字
public class Test {public static void main(String[] args){
      int x = 10;
      do {System.out.print("value of x :" + x);
         x++;
         System.out.print("\n");
      } while(x < 20);
   }
}

Python 并不反对 do-while 构造,“do”并不是一个无效的关键字。

那么,为什么 Python 不提供这种语法结构呢,这种现状的背地有何种设计考量因素呢?

在答复这个问题之前,让咱们再认真思考一下 do-while 语法能够解决什么问题,看看应用这种构造能带来什么益处?

最不言而喻的益处是:do-while 语法保障了会先执行一遍循环体代码。

它的应用场景兴许不多,然而,跟一般的 while 循环或者 for 循环语法的“条件前置 ”思维不同,它体现的是一种“ 条件后置”的编程逻辑,也是一种管制循环的常见形式。

它们的关系仿佛有点像 C/C++ 这些语言中的 i++++i操作的区别,在某些非凡场合中,兴许会更为高效。

除了这一特点,这种构造最大的利用场景其实是在 C/C++ 中非凡的do {...} while (0) 用法。这在很多开源我的项目的源码中都能找到形迹,例如 Linux、Redis 以及 CPython 解释器,等等。

这外面的数字 0 示意布尔值 False,意味着循环只会执行一遍,而后就跳出。

这样的写法是不是很诡异?所谓“循环”,个别就意味着程序领会被重复执行屡次,然而,do {...} while (0) 却偏偏只须要它执行一遍,这初看起来是有点多余啊。

这种写法次要用在宏函数的定义中,能够解决宏代码块的编译问题,使代码依照咱们的用意而正当分块。

另外,do {...} while (0) 联合 break 应用,还能够实现很优雅的跳转管制成果。

在上面的示例中,步骤 1、4 和 5 要求必须执行,而步骤 2 取决于步骤 1 的执行后果,步骤 3 则取决于步骤 2 的执行后果。

do {
  // 执行步骤 1 
  if (条件 1 失败) {break;}
  // 执行步骤 2 
  if (条件 2 失败) {break;}
  // 执行步骤 3 
  if (条件 3 失败) {break;}
} while(0);
// 执行步骤 4
// 执行步骤 5

在这种场景中,咱们的确只须要依照程序执行一遍。do-while 构造很清晰,防止造成多层条件嵌套或者设置诸多额定标记的场面。

最初还有一点,在汇编层面,do-while 比 while 更靠近汇编语言的逻辑,能够节俭应用指令,在过来的低内存时代,算得上是一种优化写法。

剖析完 do-while 的益处后,让咱们回到主题:Python 为什么不须要设计 do-while 循环语法呢?

首先,Python 离底层利用编程太远了,就不必思考汇编指令的优化了,同时,它也不波及宏的应用。

至于“条件前置”和“条件后置”的区别,其实并没有太大影响,而且,因为 Python 应用简洁优雅的缩进加冒号语法来划分代码块,导致直译过去的 do-while 语法看起来会很怪异(留神,直译的 while 的条件后没有其它内容):

do:
    pass
while False

想要引入新的语法个性,必然要恪守既定的格调习惯。其它语言的 do-while 构造直译成 Python 的话,必定不适合。

事实上,在 2003 年时,有一个 PEP 提议给 Python 加上 do-while 语法反对:

PEP-315 Enhanced While Loop

该 PEP 提议减少一个可选的 do 子句,反对将 while 循环扩大成这样子:

do:
    <setup code>
while <condition>:
    <loop body>

这不是简略地从其它语言翻译成 Python,它的 while 语句后保留了 Python 的缩进用法,并不会造成直译模式的突兀后果。

加上 while 循环自身已反对的可选的 else 子句,因而,while 残缺的语法结构是这样的:

while_stmt : ["do" ":" suite]
            "while" expression ":" suite
            ["else" ":" suite]

(PS. 在本系列的下一篇文章,咱们将解释为什么 Python 要反对 while-else 语法)

也就是说,在放弃原 while 循环语法不变的状况下,PEP-315 提议反对在 while 后面应用一个可选的 do 子句。

do 子句只会执行一遍,当它外面呈现 break 时,则跳出整个 do-while 循环;当 do 子句中呈现 continue 时,则跳出 do 子句,进到 while 的条件判断中。

有了 do 子句后,很容易就能实现 do {...} while (0) 的跳转管制成果。

然而,这个 PEP 受到了一些外围开发者的拥护。

拥护的理由是,不须要引入新的关键字和语法,仅应用现有语法就能很好地实现同样的性能:

while True:
    <setup code>
    if not <condition>:
        break
    <loop body>

Python 之父 Guido van Rossum 也持拥护意见,他的原话是:

Please reject the PEP. More variations along these lines won’t make the
language more elegant or easier to learn. They’d just save a few hasty
folks some typing while making others who have to read/maintain their code wonder what it means.

简略翻译一下,这种 do-while 语法并不会使 Python 更优雅好用,反而会产生浏览 / 保护代码的了解累赘。

就集体的感觉而言,我也不赞成引入 PEP-315 那种可选的 do-while 语法,尽管它比固定模式的 do-while 构造更为灵便和优雅一点。

最初略微总结一下,do-while 作为一种常见的循环构造,在其它语言中有所施展,它甚至还倒退出了 do {...} while (0) 的典型用法,然而,do-while 可能解决的几个问题要么在 Python 中并不存在(宏定义、汇编指令),要么就是曾经有更为适合而低成本的实现(跳转管制)。

看完这篇文章,你是否还有其它补充的内容呢?欢送交换探讨。

如果你对 Python 语言设计相干的话题感兴趣,欢送订阅 Github 上的《Python 为什么》系列文章(https://github.com/chinesehua…)

关联浏览:

Python 为什么会有个奇怪的“…”对象?

Python 函数为什么会默认返回 None?

Python 之父为什么厌弃 lambda 匿名函数?

为什么继承 Python 内置类型会出问题?!

Python 为什么举荐蛇形命名法?

正文完
 0