geekdoc-python-zh/docs/realpython/python-do-while.md

15 KiB
Raw Blame History

如何在 Python 中模拟 Do-While 循环?

原文:https://realpython.com/python-do-while/

如果你从像 CC++JavaJavaScript 这样的语言来到 Python那么你可能会错过它们的 do-while 循环结构。do-while 循环是一个常见的控制流语句,它至少执行其代码块一次,不管循环条件是真还是假。这种行为依赖于在每次迭代结束时评估循环条件这一事实。所以,第一次迭代总是运行。

这种类型的循环最常见的用例之一是接受和处理用户的输入。考虑以下用 C 编写的示例:

#include  <stdio.h> int  main()  { int  number; do  {   printf("Enter a positive number: "); scanf("%d",  &number); printf("%d\n",  number); }  while  (number  >  0);   return  0; }

这个小程序运行一个dowhile循环,要求用户输入一个正数。然后输入被存储在number中并打印到屏幕上。循环一直运行这些操作,直到用户输入一个非正数。

如果您编译并运行这个程序,那么您将得到以下行为:

Enter a positive number: 1
1
Enter a positive number: 4
4
Enter a positive number: -1
-1

循环条件number > 0在循环结束时被评估,这保证了循环的主体将至少运行一次。这个特性将 do-while 循环与常规的 while 循环区分开来,后者在开始时评估循环条件。在 while 循环中,不能保证运行循环体。如果循环条件一开始就是假的,那么肉体根本不会运行。

注意:在本教程中,你将把控制 while 或 do-while 循环的条件称为循环条件。这个概念不应该与循环的主体混淆,后者是在 C 等语言中夹在花括号之间的代码块,或者在 Python 中缩进。

使用 do-while 循环结构的一个原因是效率。例如,如果循环条件意味着高成本操作,并且循环必须运行 n 次( n ≥ 1),那么该条件将在 do-while 循环中运行 n 次。相反,常规的 while 循环将运行代价高昂的条件 n + 1 次。

Python 没有 do-while 循环结构。为什么?显然,核心开发人员从来没有为这种类型的循环找到一个好的语法。很可能,这就是吉多·范·罗苏姆 拒绝 PEP 315 的原因,这是一种在语言中添加 do-while 循环的尝试。一些核心开发人员更喜欢 do-while 循环,并期待围绕这个话题重新展开讨论。

同时,您将探索 Python 中可用的替代方法。简而言之,**如何在 Python 中模拟 do-while 循环?**在本教程中,你将学习如何使用while创建类似 do-while 循环的循环。

免费下载: 从 Python 技巧中获取一个示例章节:这本书用简单的例子向您展示了 Python 的最佳实践,您可以立即应用它来编写更漂亮的+Python 代码。

简而言之:使用一个while循环和break语句

在 Python 中模拟 do-while 循环最常见的技术是使用无限的 while循环,其中的 break 语句包装在 if语句中,该语句检查给定的条件,如果该条件为真,则中断迭代:

while True:
    # Do some processing...
    # Update the condition...
    if condition:
        break

这个循环使用True作为它的形式条件。这个技巧把循环变成了无限循环。在条件语句之前,循环运行所有需要的处理并更新中断条件。如果这个条件评估为真,那么break语句将跳出循环,程序执行将继续其正常路径。

**注意:**使用无限循环和break语句可以模拟 do-while 循环。这种技术是 Python 社区一般推荐使用的,但并不完全安全。

例如,如果在break语句之前引入一个continue语句,那么循环可能会错过中断条件,并进入一个不受控制的无限循环。

下面是如何编写与您在本教程介绍中编写的 C 程序等效的 Python:

>>> while True:
...     number = int(input("Enter a positive number: "))
...     print(number)
...     if not number > 0:
...         break
...
Enter a positive number: 1
1
Enter a positive number: 4
4
Enter a positive number: -1
-1

这个循环使用内置的 input() 函数接受用户的输入。然后使用 int() 将输入转换成整数。如果用户输入一个小于或等于0的数字,那么break语句运行,循环终止。

有时,您会遇到需要保证循环至少运行一次的情况。在那些情况下,你可以像上面一样使用whilebreak。在下一节中,您将编写一个猜数字游戏,该游戏使用这样一个 do-while 循环来接受和处理用户在命令行中的输入。

Remove ads

Do-While 循环在实践中是如何工作的?

do-while 循环最常见的用例是接受并处理用户的输入。作为一个实际的例子,假设您有一个用 JavaScript 实现的猜数字游戏。代码使用一个dowhile循环来处理用户的输入:

 1// guess.js 2
 3const  LOW  =  1; 4const  HIGH  =  10; 5
 6let  secretNumber  =  Math.floor(Math.random()  *  HIGH)  +  LOW; 7let  clue  =  ''; 8let  number  =  null; 9
10do  {  11  let  guess  =  prompt(`Guess a number between ${LOW} and ${HIGH}  ${clue}`); 12  number  =  parseInt(guess); 13  if  (number  >  secretNumber)  { 14  clue  =  `(less than ${number})`; 15  }  else  if  (number  <  secretNumber)  { 16  clue  =  `(greater than ${number})`; 17  } 18}  while  (number  !=  secretNumber);  19
20alert(`You guessed it! The secret number is ${number}`);

这个脚本做了几件事。下面是正在发生的事情的分类:

  • 第 3 行和第 4 行定义了两个常数来界定秘密数字将存在的间隔。

  • 第 6 行到第 8 行定义了变量来存储秘密数字、线索消息和number的初始值,它将保存用户的输入。

  • 第 10 行开始一个dowhile循环来处理用户的输入,并确定用户是否已经猜出了密码。

  • 第 11 行定义了一个本地变量guess,用来存储命令行提供的用户输入。

  • 第 12 行使用parseInt()将输入值转换成整数。

  • 第 13 行定义了一个条件语句,检查输入数字是否大于秘密数字。如果是这种情况,那么clue被设置为适当的消息。

  • 第 15 行检查输入的数字是否小于密码,然后相应地设置clue

  • 第 18 行定义循环条件,检查输入的数字是否与密码不同。在这个具体的例子中,循环将继续运行,直到用户猜出密码。

  • 第 20 行最后启动一个警告框,通知用户猜测成功。

现在说你想把上面的例子翻译成 Python 代码。Python 中一个等价的猜数字游戏看起来像这样:

# guess.py

from random import randint

LOW, HIGH = 1, 10

secret_number = randint(LOW, HIGH)
clue = ""

while True:
    guess = input(f"Guess a number between {LOW} and {HIGH}  {clue} ")
    number = int(guess)
    if number > secret_number:
        clue = f"(less than {number})"
    elif number < secret_number:
        clue = f"(greater than {number})"
    else:
 break 
print(f"You guessed it! The secret number is {number}")

这段 Python 代码的工作方式就像它的等效 JavaScript 代码一样。主要区别在于,在这种情况下,您使用的是常规的while循环,因为 Python 没有dowhile循环。在这个 Python 实现中,当用户猜出秘密数字时,就会运行else子句,从而打破循环。代码的最后一行打印成功的猜测消息。

使用一个无限循环和一个break语句,就像你在上面的例子中所做的那样,是在 Python 中模拟 do-while 循环最广泛使用的方法。

Do-While 和 While 循环有什么区别?

简而言之do-while 循环和 while 循环的主要区别在于,前者至少执行一次循环体,因为循环条件是在最后检查的。另一方面,如果条件评估为 true则执行常规 while 循环的主体,这在循环开始时进行测试。

下表总结了这两种循环的主要区别:

在…期间 做一会儿
是一个入口控制循环 是一个出口控制循环
仅在循环条件为真时运行 运行,直到循环条件变为假
首先检查条件,然后执行循环体 执行循环体,然后检查条件
如果循环条件最初为假,则执行循环体零次 不管循环条件的真值是多少,至少执行一次循环体
对于 n 次迭代,检查循环条件 n + 1 次 检查循环条件 n 次,其中 n 为迭代次数

while 循环是一个控制流结构它提供了一个通用的通用循环。它允许您在给定条件保持为真的情况下重复运行一组语句。do-while 循环的用例更加具体。它主要用于只有在循环体至少已经运行过一次的情况下,检查循环条件才有意义。

在 Python 中,可以使用什么替代方法来模拟 Do-While 循环?

至此,您已经了解了在 Python 中模拟 do-while 循环的推荐或最常用的方法。然而Python 在模拟这种类型的循环时非常灵活。一些程序员总是使用无限的while循环和break语句。其他程序员使用他们自己的公式。

在本节中,您将了解一些模拟 do-while 循环的替代技术。第一种方法是在循环开始之前运行第一个操作*。第二种选择意味着使用一个循环条件,在循环开始之前,该条件被初始设置为真值。*

循环前的第一个操作

正如您已经了解到的do-while 循环最相关的特性是循环体总是至少运行一次。要使用一个while循环来模拟这个功能,您可以在循环开始之前获取循环体并运行它。然后你可以在循环中重复这个物体。

这个解决方案听起来很重复,如果你不使用某种技巧的话。幸运的是,您可以使用一个函数来打包循环体并防止重复。使用这种技术,您的代码将如下所示:

condition = do_something()

while condition:
    condition = do_something()

do_something()的第一次调用保证了所需的功能至少运行一次。只有当condition为真时,循环内部对do_something()的调用才会运行。注意,您需要在每次迭代中更新循环条件,以使该模式正确工作。

下面的代码展示了如何使用这种技术实现猜数字游戏:

# guess.py

from random import randint

LOW, HIGH = 1, 10

secret_number = randint(LOW, HIGH)
clue = ""

def process_move(clue):
    user_input = input(f"Guess a number between {LOW} and {HIGH}  {clue} ")
    number = int(user_input)
    if number > secret_number:
        clue = f"(less than {number})"
    elif number < secret_number:
        clue = f"(greater than {number})"
    return number, clue

number, clue = process_move(clue)  # First iteration 
while number != secret_number:
 number, clue = process_move(clue) 
print(f"You guessed it! The secret number is {number}")

在这个新版本的猜数字游戏中,你将所有循环的功能都打包到process_move()中。这个函数返回当前数字,您将在以后检查循环条件时使用它。它还返回线索消息。

注意process_move()在循环开始前运行一次,模仿 do-while 循环的主要特征,至少运行一次它的主体。

在循环内部,您调用函数来运行游戏的主要功能,并相应地更新循环条件。

Remove ads

使用初始真循环条件

使用初始设置为True的循环条件是模拟 do-while 循环的另一种选择。在这种情况下,您只需要在循环开始运行之前将循环条件设置为True。这种做法可以确保循环体至少运行一次:

do = True

while do:
    do_something()
    if condition:
        do = False

这个替代构造与您在上一节中使用的非常相似。主要区别在于循环条件是一个在循环内部更新的布尔变量。

这种技术也类似于使用无限while循环和break语句的技术。然而,这种方法更显而易见,可读性更好,因为它允许您使用描述性的变量名,而不是简单的break语句和像True这样的硬编码条件。

**注意:**有时给布尔变量命名更自然,这样你就可以把它设置为True来打破循环。在这些情况下,您可以用类似于while not done:的东西开始循环,并在循环内将done设置为True

您可以使用这种技术来重写您的数字猜测游戏,如下面的代码示例所示:

# guess.py

from random import randint

LOW, HIGH = 1, 10

secret_number = randint(LOW, HIGH)
clue = ""
number_guessed = False 
while not number_guessed:
    user_input = input(f"Guess a number between {LOW} and {HIGH}  {clue} ")
    number = int(user_input)
    if number > secret_number:
        clue = f"(less than {number})"
    elif number < secret_number:
        clue = f"(greater than {number})"
    else:
 number_guessed = True 
print(f"You guessed it! The secret number is {number}")

在本例中,首先定义一个布尔变量number_guessed,它允许您控制循环。在循环内部,您像往常一样处理用户的输入。如果用户猜出了密码,那么number_guessed被设置为True,程序跳出循环执行。

结论

在本教程中,你已经学会了用 Python 模拟一个 do-while 循环。这种语言没有这种循环结构,这种结构在 C、C++、Java 和 JavaScript 等语言中可以找到。您了解了在常规 while 循环的帮助下,您总是可以编写 do-while 循环,并且可以使用几种不同模式中的一种来完成它。

模拟 do-while 循环最常见的技术是创建一个无限while循环,在循环体的末尾添加一个条件语句。该条件控制循环,并使用 break 语句跳出循环。

您还了解了如何使用一些替代技术来提供与 do-while 循环相同的功能。您的选择包括在循环之前进行第一组操作,或者使用一个初始设置为True的布尔变量来控制循环。

有了这些知识,您就可以开始在自己的 Python 代码中模拟 do-while 循环了。

免费下载: 从 Python 技巧中获取一个示例章节:这本书用简单的例子向您展示了 Python 的最佳实践,您可以立即应用它来编写更漂亮的+Python 代码。**