社区编辑申请
注册/登录
Python 为什么不设计 Do-while 循环结构?
开发 后端
在某些编程语言中,例如 C/C++、C#、PHP、Java、JavaScript 等等,do-while 是一种基本的循环结构。

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

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

流程图如下(Java 示例):

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

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 的执行结果。

  1. do { 
  2.   // 执行步骤 1  
  3.   if (条件1失败) { 
  4.     break; 
  5.   } 
  6.   // 执行步骤 2  
  7.   if (条件2失败) { 
  8.     break; 
  9.   } 
  10.   // 执行步骤 3  
  11.   if (条件3失败) { 
  12.     break; 
  13.   } 
  14. } while(0); 
  15. // 执行步骤 4 
  16. // 执行步骤 5 

在这种场景中,我们确实只需要按照顺序执行一遍。do-while 结构很清晰,避免造成多层条件嵌套或者设置诸多额外标记的局面。

最后还有一点,在汇编层面,do-while 比 while 更接近汇编语言的逻辑,可以节省使用指令,在过去的低内存时代,算得上是一种优化写法。

分析完 do-while 的好处后,让我们回到主题:Python 为什么不需要设计 do-while 循环语法呢?

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

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

  1. do: 
  2.     pass 
  3. while False 

想要引入新的语法特性,必然要遵守既定的风格习惯。其它语言的 do-while 结构直译成 Python 的话,肯定不合适。

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

PEP-315 Enhanced While Loop

该 PEP 提议增加一个可选的 do 子句,支持将 while 循环扩展成这样子:

  1. do: 
  2.     <setup code> 
  3. while <condition>: 
  4.     <loop body> 

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

加上 while 循环本身已支持的可选的 else 子句,因此,while 完整的语法结构是这样的:

  1. while_stmt : ["do" ":" suite] 
  2.             "while" expression ":" suite 
  3.             ["else" ":" suite] 

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

也就是说,在保持原 while 循环语法不变的情况下,PEP-315 提议支持在 while 前面使用一个可选的 do 子句。

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

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

但是,这个 PEP 遭到了一些核心开发者的反对。

反对的理由是,不需要引入新的关键字和语法,仅使用现有语法就能很好地实现同样的功能:

  1. while True
  2.     <setup code> 
  3.     if not <condition>: 
  4.         break 
  5.     <loop body> 

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

Guido的回复

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猫」,可以通过以下二维码关注。转载本文请联系Python猫公众号。

 

责任编辑:武晓燕 来源: Python猫
相关推荐

2022-04-11 11:38:44

Python代码游戏

2022-05-03 22:25:57

Python浏览器语言

2022-04-19 08:29:12

Python机器学习

2022-05-03 23:44:21

Python动态链接库Ctypes

2022-05-10 07:24:19

2022-05-17 09:14:50

聚类算法python

2022-05-11 08:23:54

自动化测试软件测试

2022-05-02 16:27:01

JavaScriptHTMLPython

2022-05-07 07:26:05

PyScriptHTMLPython 代码

2022-05-16 09:34:17

Python可视化图表

2022-04-11 13:37:54

编程语言PythonMATLAB

2022-01-27 09:35:45

2022-05-20 08:55:02

py文件exepython

2022-04-24 10:12:25

Python软件包代码

2022-04-07 15:28:16

HarmonyOS鸿蒙操作系统

2022-04-12 08:43:21

Python内置模块

2022-05-11 12:12:32

ScapyPython网络包

2022-04-17 23:09:07

深度学习人工智能芯片

2022-03-11 10:53:32

UML建模语言

2022-05-24 07:51:05

测试模型测试单元测试

同话题下的热门内容

简单的六种防止数据重复提交的方法!用Python进行人脸识别「包括源代码」超实用!教你用 Python 获取并下载美股数据Python或R:哪种编程语言更适合数据科学?在 Go 中实现一个支持并发的 TCP 服务端用 XML 和 Java 构建树莓派打印机的用户界面C语言:如何给全局变量起一个别名?什么!Sentinel流控规则可以这样玩?

编辑推荐

使用Kotlin做开发一个月后的感想面试官问你什么是消息队列?把这篇甩给他!五大自动化测试的Python框架图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)2018年最流行的十大编程语言,其中包括你用的语言吗?
我收藏的内容
点赞
收藏

51CTO技术栈公众号