Python & AI Tutorials Logo
Python 编程

11. 使用 while 循环重复执行操作

程序经常需要多次重复执行某些操作。你已经在第 8 章看到如何使用 if 语句做出决策,但如果你需要反复执行某个动作,直到满足某个条件为止,该怎么办?这就是循环(loop)发挥作用的地方。

Python 提供两种主要的循环:while 循环和 for 循环。在本章中,我们将重点介绍 while 循环,它会在条件保持为真时重复执行一段代码。更适合用来遍历序列的 for 循环,将在第 12 章介绍。

理解 while 循环是编写程序的基础,这类程序可以反复处理数据、验证用户输入、实现游戏循环,以及处理许多其他真实世界的编程场景。

11.1) while 循环的结构

while 循环(while loop) 会在指定条件求值为 True 时反复执行一段代码块。一旦条件变为 False,循环就会停止,程序继续执行循环之后的代码。

基本 while 循环语法

while 循环的结构如下所示:

python
while condition:
    # 要重复的代码块
    # 只要 condition 为 True,这段代码就会运行

condition 可以是任何会求值为布尔值的表达式(或者可以解释为真值或假值,正如我们在第 7 章学习的那样)。while 语句下方缩进的代码块称为循环体(loop body),只要条件保持为 True,它就会反复执行。

我们来看一个简单示例:

python
# 从 1 数到 5
count = 1
while count <= 5:
    print(f"Count is: {count}")
    count = count + 1  # 递增 count
print("Loop finished!")

Output:

Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5
Loop finished!

一步一步来看它是如何工作的:

  1. 我们把 count 初始化为 1
  2. 检查条件 count <= 5。由于 1 <= 5True,循环体执行
  3. 在循环内部,我们打印当前的 count,然后将其加 1
  4. 循环体完成后,Python 返回到 while 语句并再次检查条件
  5. 这个过程会重复,直到 count 变为 6,此时 6 <= 5False,循环终止
  6. 程序继续执行循环之后的代码

关键点是:条件会在每次迭代(iteration)(循环体的每次重复)之前进行检查。如果条件一开始就是 False,循环体根本不会执行:

python
count = 10
while count <= 5:
    print("This will never print")
print("Loop skipped entirely")

Output:

Loop skipped entirely

由于 10 <= 5 从一开始就是 False,循环体从不运行。

修改循环变量的重要性

为了让 while 循环最终停止,循环内部必须有某些操作把条件从 True 变为 False。这通常意味着要修改条件中使用的变量。如果你忘记这样做,就会创建一个无限循环(infinite loop)(我们将在下一节详细讨论)。

下面这个示例演示了为什么更新循环变量很重要:

python
# 计算从 1 到 10 的数字之和
total = 0
number = 1
 
while number <= 10:
    total = total + number  # 将当前数字加到 total
    number = number + 1     # 移动到下一个数字
 
print(f"The sum of numbers from 1 to 10 is: {total}")

Output:

The sum of numbers from 1 to 10 is: 55

在这个示例中,我们在遍历数字的同时累积求和。totalnumber 都会在每次迭代中变化,但正是 number 的修改确保了当 number 变为 11 时循环最终会终止。

带用户输入的 while 循环

while 循环一个很实用的用途是:持续处理用户输入,直到满足特定条件为止。我们来创建一个简单的猜数字游戏:

python
# 简单的猜数字游戏
secret_number = 7
guess = 0
 
while guess != secret_number:
    guess = int(input("Guess the number (1-10): "))
    
    if guess < secret_number:
        print("Too low! Try again.")
    elif guess > secret_number:
        print("Too high! Try again.")
    else:
        print("Correct! You guessed it!")

这个循环会持续要求用户猜测,直到用户输入正确的数字为止。每次迭代都会处理一次猜测并给出反馈。当 guess 等于 secret_number 时,循环自然终止,使条件 guess != secret_number 变为 False

带多个条件的 while 循环

你可以使用布尔运算符(andornot)来创建更复杂的循环条件,正如我们在第 9 章学到的那样:

python
# 处理输入,直到用户输入 "quit" 或者达到 5 次尝试
attempts = 0
user_input = ""
 
while user_input != "quit" and attempts < 5:
    user_input = input("Enter a command (or 'quit' to exit): ")
    attempts += 1
    
    if user_input == "quit":
        print("Goodbye!")
    else:
        print(f"You entered: {user_input}")
        print(f"Attempts remaining: {5 - attempts}")
 
if attempts >= 5 and user_input != "quit":
    print("Maximum attempts reached.")

只要两个条件都为真:用户还没有输入 "quit" 并且尝试次数没有超过 5 次,这个循环就会继续。当任一条件变为假时,循环终止。

可视化 while 循环的执行过程

下面的流程图展示了 while 循环是如何执行的:

True

False

开始

初始化变量

检查条件

执行循环体

更新变量

继续执行循环之后的代码

结束

循环会创建一个周期:检查条件、若条件为真则执行循环体、更新变量,然后再次检查条件。这个周期会持续,直到条件变为假。

11.2) 无限循环以及如何避免它们

无限循环(infinite loop) 是指永远不会终止的循环,因为它的条件永远不会变为 False。无限循环是初学者在使用 while 循环时最常见的错误之一,它们会导致程序无限期卡住。

什么会导致无限循环?

无限循环最常见的原因是:忘记修改会影响循环条件的变量。我们来看一个有问题的示例:

python
# 警告:无限循环——仅用于演示
# 问题:count 从未被修改
count = 1
while count <= 5:
    print(f"Count is: {count}")
    # Missing: count += 1

如果你运行这段代码,它会永远打印 "Count is: 1",因为 count 始终保持为 1,而 1 <= 5 永远为 True。条件从不改变。

如何识别这是一个无限循环: 查看循环条件(count <= 5),然后检查循环体内部是否有任何内容修改了 count。如果没有,并且条件一开始为 True,那你就有一个无限循环。

下面是修正后的版本:

python
# 正确版本:进行适当的递增
count = 1
while count <= 5:
    print(f"Count is: {count}")
    count += 1  # 这确保循环最终会终止

Output:

Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5

使用安全上限调试无限循环

在开发包含循环的代码时,在测试期间添加一个安全上限有助于防止意外的无限循环:

python
# 开发阶段的安全上限
count = 1
iterations = 0
max_iterations = 100  # 安全上限
 
while count <= 5 and iterations < max_iterations:
    print(f"Count is: {count}")
    count += 1
    iterations += 1
 
if iterations >= max_iterations:
    print("WARNING: Maximum iterations reached. Check for infinite loop.")

这种模式增加了一个计数器来跟踪循环执行了多少次。如果它达到安全上限,就说明你的循环逻辑可能出了问题。一旦你确信循环能正确工作,就可以移除这个安全上限。

带用户输入的无限循环

另一个与无限循环相关的常见场景是用户输入校验:

python
# 警告:可能出现无限循环——仅用于演示
# 问题:如果用户从不输入有效内容,循环就永远不会结束
age = -1
while age < 0:
    age = int(input("Enter your age: "))
    # 如果用户输入负数,循环会继续

如果用户最终输入一个非负数,这个循环就能正确工作;但如果用户一直输入负值,它就会成为无限循环。虽然对某些程序来说这可能是可以接受的(你希望一直询问直到收到有效输入),但理解这一点很重要:循环能否终止完全取决于用户行为。

一个更健壮的方法可能包含退出方式:

python
# 更好的方式:提供退出选项
age = -1
while age < 0:
    user_input = input("Enter your age (or 'quit' to exit): ")
    
    if user_input.lower() == 'quit':
        print("Exiting program.")
        age = 0  # 设置为有效值以退出循环
    else:
        age = int(user_input)
        if age < 0:
            print("Age must be non-negative. Please try again.")
 
if age > 0:
    print(f"Your age is: {age}")

由逻辑错误导致的无限循环

有时无限循环是由于更新变量时出现了逻辑错误:

python
# 警告:无限循环——仅用于演示
# 问题:count 被递减而不是递增
count = 1
while count <= 5:
    print(f"Count is: {count}")
    count -= 1  # 错误:这会让 count 变小,而不是变大

这会创建一个无限循环,因为 count1 开始变为 0-1-2 等。由于负数总是小于或等于 5,条件 count <= 5 将永远保持为 True

修正后的版本:

python
count = 1
while count <= 5:
    print(f"Count is: {count}")
    count += 1  # 正确:递增以最终超过 5

调试无限循环

如果你在运行 Python 脚本时不小心创建了无限循环,你可以在终端中按 Ctrl+C(或 Mac 上的 Cmd+C)停止它。这会向 Python 发送键盘中断信号,从而停止程序。

如何避免无限循环:

  1. 始终确保循环条件有可能变为 False:检查条件里的变量是否在循环内部被修改
  2. 使用正确的比较运算符:确保 <=<!= 等符合你的意图
  3. 先用小数值测试:在运行可能执行很多次的循环之前,先用较小的上限测试
  4. 添加调试打印语句:临时打印循环变量,看看它如何变化:
  5. 在开发期间使用安全上限:如前所示,在测试时添加最大迭代次数计数器

11.3) 在 while 循环中使用 break 和 continue

Python 提供了两个特殊语句,让你对循环执行有更强的控制能力:breakcontinue。这些语句允许你根据执行过程中出现的条件来改变循环的正常流程。

11.3.1) break 语句

break 语句会立即终止循环,不管循环条件是什么。当 Python 遇到 break 时,它会完全退出循环,并继续执行循环之后的代码。

下面是一个简单示例:

python
# 当达到某个特定值时退出循环
count = 1
while count <= 10:
    if count == 5:
        print("Reached 5, stopping loop")
        break
    print(f"Count: {count}")
    count += 1
 
print("Loop exited")

Output:

Count: 1
Count: 2
Count: 3
Count: 4
Reached 5, stopping loop
Loop exited

注意:当 count 等于 5 时,break 语句执行,循环立即终止。即使条件 count <= 10 仍然会是 True,循环也永远不会到达 count = 6

break 如何改变循环流程

理解 break 如何改变正常的循环执行至关重要。下面的流程图展示了其中的差异:

False

True

Yes

No

开始循环

检查 while 条件

正常退出循环

执行循环体代码

遇到 break?

立即退出循环

继续执行到循环体末尾

循环之后的代码

关键点:break 提供了一条从循环中立即退出的路径,绕过循环体剩余代码以及条件检查。

break 的实际用途:输入校验

break 最常见的用途之一是在收到有效输入时退出循环:

python
# 持续询问,直到收到有效输入为止
while True:
    age_input = input("Enter your age (must be positive): ")
    
    # 尝试转换为整数
    try:
        age = int(age_input)
        
        # 检查是否有效
        if age > 0:
            print(f"Thank you! Your age is {age}")
            break  # 在输入有效时退出循环
        else:
            print("Age must be positive. Please try again.")
    except ValueError:
        print("That's not a valid number. Please try again.")
 
print("Input validation complete")

这种模式使用 while True: 创建一个有意的无限循环,然后在收到有效输入时用 break 退出。它比试图管理一个复杂的循环条件更简洁。(注意:这里我们使用了 tryexcept,我们会在第 VII 部分详细学习。现在只需要理解:它用于捕获将输入转换为整数时发生的错误。)

带多个条件的 break

你可以将 break 与复杂条件结合使用,在满足多个条件之一时退出循环:

python
# 在用户输入中搜索某个特定项
search_term = "python"
attempts = 0
max_attempts = 5
 
while attempts < max_attempts:
    user_input = input("Enter a word (or 'quit' to exit): ").lower()
    attempts += 1
    
    if user_input == 'quit':
        print("User requested exit")
        break
    
    if user_input == search_term:
        print(f"Found '{search_term}'!")
        break
    
    print(f"'{user_input}' is not '{search_term}'. Try again.")
    print(f"Attempts remaining: {max_attempts - attempts}")
 
if attempts >= max_attempts:
    print("Maximum attempts reached")

这个循环可以通过三种方式退出:

  1. 用户输入 "quit"(第一个 break
  2. 用户输入搜索词(第二个 break
  3. 达到最大尝试次数(循环条件变为 False

11.3.2) continue 语句

continue 语句会跳过当前这次迭代的剩余部分,并回到循环条件检查处。不同于会完全退出循环的 breakcontinue 只是跳到下一次迭代。

下面是一个基础示例:

python
# 只打印 1 到 10 的奇数
count = 0
while count < 10:
    count += 1
    
    if count % 2 == 0:  # 如果是偶数
        continue  # 跳过剩余部分,进入下一次迭代
    
    print(f"Odd number: {count}")

Output:

Odd number: 1
Odd number: 3
Odd number: 5
Odd number: 7
Odd number: 9

它的工作方式:

  1. count 在每次迭代开始时递增
  2. 如果 count 是偶数(count % 2 == 0),就会执行 continue
  3. continue 会跳过 print 语句,并跳回 while 条件
  4. 如果 count 是奇数,continue 不执行,于是 print 语句运行

continue 如何改变循环流程

下面的流程图展示了 continue 如何影响循环执行:

False

True

Yes

No

开始循环

检查 while 条件

退出循环

执行 continue 检查之前的代码

遇到 continue?

执行循环体剩余代码

breakcontinue 的关键区别:

  • break:完全退出循环,跳到循环之后的代码
  • continue:跳过当前迭代的剩余代码,跳回条件检查

continue 的重要放置位置说明

注意,count += 1 位于 continue 之前。如果我们把它放在后面,偶数会触发 continue 跳过递增,从而导致无限循环:

python
# 警告:无限循环——仅用于演示
# 问题:对于偶数,continue 会跳过递增
count = 0
while count < 10:
    if count % 2 == 0:
        continue  # 跳过下面所有内容,包括 count += 1
    count += 1  # 错误:对偶数来说,这行永远不会运行
    print(f"Odd number: {count}")

count0(偶数)时,continue 执行,跳过 count += 1。循环再次检查 0 < 10,然后无限重复。

规则:始终确保会影响条件的循环变量在任何可能跳过循环体其余部分的 continue 语句之前被更新。

continue 的实际用途:过滤数据

当你在处理数据且希望跳过某些项时,continue 非常有用:

python
# 只处理有效的分数
score_count = 0
total_score = 0
attempts = 0
 
while attempts < 5:
    score_input = input(f"Enter score {attempts + 1} (or 'skip' to skip): ")
    attempts += 1
    
    if score_input.lower() == 'skip':
        print("Skipping this score")
        continue  # 跳到下一次迭代
    
    try:
        score = int(score_input)
        
        if score < 0 or score > 100:
            print("Score must be between 0 and 100. Skipping.")
            continue  # 跳过无效分数
        
        # 有效分数——处理它
        total_score += score
        score_count += 1
        print(f"Score recorded: {score}")
        
    except ValueError:
        print("Invalid input. Skipping.")
        continue
 
if score_count > 0:
    average = total_score / score_count
    print(f"\nAverage of {score_count} valid scores: {average:.1f}")
else:
    print("\nNo valid scores entered")

这个示例演示了 continue 的多种用法:

  • 当用户输入 "skip" 时跳过
  • 当分数超出有效范围时跳过
  • 当输入不是有效数字时跳过

每个 continue 都会阻止该分数被加入总分,但循环仍会继续到下一次尝试。

结合使用 break 和 continue

你可以在同一个循环中同时使用 breakcontinue 来实现更复杂的控制:

python
# 处理数字,直到总和超过 100,跳过负数
total = 0
count = 0
 
while True:
    number_input = input("Enter a number (or 'done' to finish): ")
    
    if number_input.lower() == 'done':
        print("User finished entering numbers")
        break  # 退出循环
    
    try:
        number = int(number_input)
        
        if number < 0:
            print("Negative numbers not allowed. Skipping.")
            continue  # 跳到下一次迭代
        
        total += number
        count += 1
        print(f"Added {number}. Current total: {total}")
        
        if total > 100:
            print("Total exceeded 100. Stopping.")
            break  # 达到上限时退出循环
            
    except ValueError:
        print("Invalid input. Skipping.")
        continue
 
print(f"\nFinal total: {total} (from {count} numbers)")

这个循环演示了:

  • 用户输入 "done" 时用 break 退出
  • continue 跳过负数
  • continue 跳过无效输入
  • 当总和超过 100 时用 break 退出

11.4) 在 while 循环中使用 else

Python 有一个许多其他编程语言都没有的独特特性:你可以给 while 循环附加一个 else 子句。这个 else 代码块只会在循环正常完成时执行(也就是循环条件变为 False,且没有遇到 break 语句)。

while 搭配 else 的基本语法

语法如下所示:

python
while condition:
    # 循环体
else:
    # 仅当循环正常完成时才执行
    # (没有被 break 中断)

我们来看一个简单示例:

python
# 使用 else 子句从 1 数到 5
count = 1
while count <= 5:
    print(f"Count: {count}")
    count += 1
else:
    print("Loop completed normally")
 
print("Program continues")

Output:

Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Loop completed normally
Program continues

else 代码块会执行,因为循环一直运行到条件(count <= 5)变为 False。循环在没有被中断的情况下“正常”完成。

else 何时不会执行:break 语句

else 子句的关键行为是:如果循环是被 break 语句终止的,它就不会执行:

python
# 使用 break 搜索一个数字
count = 1
target = 3
 
while count <= 5:
    print(f"Checking: {count}")
    if count == target:
        print(f"Found {target}!")
        break
    count += 1
else:
    print("Target not found in range")
 
print("Search complete")

Output:

Checking: 1
Checking: 2
Checking: 3
Found 3!
Search complete

注意:else 代码块("Target not found in range")并没有执行,因为循环被 break 终止了。这是关键区别:else 只在循环正常退出(条件变为 False)时运行,而不是通过 break 退出时运行。

现在我们来看看当目标没有找到时会发生什么:

python
# 搜索一个不存在的数字
count = 1
target = 7  # 不在 1-5 范围内
 
while count <= 5:
    print(f"Checking: {count}")
    if count == target:
        print(f"Found {target}!")
        break
    count += 1
else:
    print("Target not found in range")
 
print("Search complete")

Output:

Checking: 1
Checking: 2
Checking: 3
Checking: 4
Checking: 5
Target not found in range
Search complete

这一次,循环在没有找到目标的情况下完成了所有迭代,因此条件 count <= 5 最终变为 Falseelse 代码块执行。

else 如何配合循环完成执行

下面的流程图展示了带 else 子句时的执行路径:

False

True

Yes

No

开始

检查 while 条件

执行 else 代码块

执行循环体

遇到 break?

跳过 else 代码块

继续执行循环之后的代码

只有当循环条件自然变为 False 时,才会到达 else 代码块。如果遇到 break,流程会直接跳过 else 代码块,进入循环之后的代码。

实际用途:搜索操作

else 子句在搜索操作中特别有用,你通常希望知道某个东西是否被找到:

python
# 在多次尝试中查找有效密码
valid_password = "python123"
max_attempts = 3
attempts = 0
 
while attempts < max_attempts:
    password = input(f"Enter password (attempt {attempts + 1}/{max_attempts}): ")
    attempts += 1
    
    if password == valid_password:
        print("Access granted!")
        break
else:
    print("Access denied. Maximum attempts exceeded.")
    print("Account locked.")

如果用户输入了正确密码,break 执行并跳过 else 代码块。如果所有尝试都用完仍未成功,循环正常完成,else 代码块执行,表示失败。

else 与 continue

continue 语句不会阻止 else 代码块执行。只有 break 才会阻止:

python
# continue 不会影响 else 的执行
count = 0
while count < 5:
    count += 1
    if count == 3:
        print(f"Skipping {count}")
        continue  # 跳到下一次迭代
    print(f"Processing {count}")
else:
    print("Loop completed normally (continue doesn't prevent this)")

Output:

Processing 1
Processing 2
Skipping 3
Processing 4
Processing 5
Loop completed normally (continue doesn't prevent this)

else 代码块会执行,因为循环正常完成了。continue 只影响单次迭代,不影响整体循环是否完成。

对比:有 break 与没有 break 时的 else

我们来做一个并排对比:

python
# 示例 1:寻找第一个能被 7 整除的数(带 break)
print("Finding first number divisible by 7:")
number = 1
while number <= 20:
    if number % 7 == 0:
        print(f"Found: {number}")
        break
    number += 1
else:
    print("No number divisible by 7 found in range")
print()
 
# 示例 2:检查所有数字(没有 break)
print("Checking all numbers for divisibility by 7:")
number = 1
while number <= 20:
    if number % 7 == 0:
        print(f"Found: {number}")
    number += 1
else:
    print("Finished checking all numbers")

Output:

Finding first number divisible by 7:
Found: 7
 
Checking all numbers for divisibility by 7:
Found: 7
Found: 14
Finished checking all numbers

在第一个示例中,break 在找到第一个匹配项后停止循环,因此 else 不执行。在第二个示例中,循环检查所有数字并正常完成,因此 else 执行。

何时在 while 循环中使用 else

else 子句最有用的场景是:

  1. 搜索操作:你想知道是否找到了某个东西
  2. 限制尝试次数的校验:你需要处理所有尝试都耗尽的情况
  3. 带提前退出的处理流程:你希望对“全部完成”与“提前停止”采取不同的行为

然而,对于来自其他语言的程序员(那些语言没有这个特性)来说,循环里的 else 可能会令人困惑。有时用一个标志变量会更清晰:

python
# 使用 else 子句
attempts = 0
while attempts < 3:
    password = input("Enter password: ")
    attempts += 1
    if password == "secret":
        print("Access granted")
        break
else:
    print("Access denied")
 
# 使用标志变量的等价写法(有时更清晰)
attempts = 0
access_granted = False
while attempts < 3:
    password = input("Enter password: ")
    attempts += 1
    if password == "secret":
        print("Access granted")
        access_granted = True
        break
 
if not access_granted:
    print("Access denied")

两种方式都可行。请选择在你的具体场景中能让代码更清晰的写法。

理解 while 循环搭配 else 的用法,会为你提供另一种编写清晰、表达力强的代码的工具,尤其是在搜索与校验场景中,你需要区分“找到”与“未找到”或“成功”与“尝试全部用尽后的失败”。


在本章中,我们深入探索了 while 循环,学习了如何:

  • 构造基于条件重复执行代码的循环
  • 通过正确更新循环变量来避免无限循环
  • 在需要时使用 break 提前退出循环
  • 根据条件使用 continue 跳过某些迭代
  • 使用 else 处理循环在没有 break 的情况下正常完成的情况

这些工具让你能够强力控制程序中的重复执行。在下一章中,我们将学习 for 循环,它提供了一种更便捷的方式来遍历字符串、列表(list)和范围等序列。

© 2025. Primesoft Co., Ltd.
support@primesoft.ai