python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python while循环

Python基础指南之while循环的基本结构与使用场景详解

作者:星河耀银海

本文将带你彻底搞懂while循环,从基础语法到经典模式再到无限循环的实战应用,一次掌握,同时揭秘常见陷阱如off-by-one错误和变量污染,并给出while vs for的选型建议,让你的代码效率翻倍

一、开篇:重复——编程的真正力量所在

如果说条件判断让程序有了"选择能力",那么循环则赋予了程序"重复执行"的能力。计算机真正的价值不在于算一次,而在于能不知疲倦地重复计算成千上万次

来看一个简单的例子:

# 不用循环:打印1到5
print(1)
print(2)
print(3)
print(4)
print(5)

# 用循环:打印1到100只需3行
i = 1
while i <= 100:
    print(i)
    i += 1

这就是循环的威力——用几行代码替代几十行、几百行重复代码。

Python中有两种循环:while循环(基于条件)和for循环(基于迭代)。今天我们先深入掌握while循环,从基本结构到实战应用,再到性能考量与常见陷阱。

二、while循环的基本结构

2.1 基本语法

# while循环的基本语法
# while 条件:
#     循环体(条件为真时重复执行)
# else:              # 可选
#     else代码块     # 条件变为假时执行(没有被break中断时)

# 最简单的例子
count = 0
while count < 5:
    print(f"第 {count + 1} 次循环")
    count += 1

print("循环结束")

# 输出:
# 第 1 次循环
# 第 2 次循环
# 第 3 次循环
# 第 4 次循环
# 第 5 次循环
# 循环结束

2.2 while循环的三个关键要素

每个while循环都应该具备三个要素:

# 1. 初始化:循环开始前的状态设置
# 2. 条件:决定循环是否继续的布尔表达式
# 3. 更新:改变循环变量,让循环能走向终止

# 三要素示例
i = 0              # ① 初始化:设置计数器
while i < 10:      # ② 条件:检查是否应该继续
    print(i)
    i += 1         # ③ 更新:修改计数器,使条件最终变为False

# ⚠️ 缺少更新 → 无限循环
# i = 0
# while i < 10:
#     print(i)
#     # 忘记 i += 1 → 永远打印0!

# ⚠️ 条件永远为True → 无限循环
# while True:
#     print("这永远不会停止...")

2.3 条件就是真值测试

while的条件和if的条件一样,使用真值测试:

# while后面可以是任何返回布尔值的表达式
# 同样运用了真值测试规则

# 计数器模式
count = 3
while count > 0:
    print(f"倒计时: {count}")
    count -= 1
print("发射!🚀")

# 哨兵值模式
user_input = ""
while user_input != "quit":
    user_input = input("请输入(输入quit退出): ")
    print(f"你输入了: {user_input}")

# 真值测试模式
data = [1, 2, 3]
while data:          # 等价于 while len(data) > 0
    item = data.pop()
    print(f"弹出: {item}")

# 条件可以是复杂的逻辑表达式
attempts = 0
success = False
while attempts < 5 and not success:
    # 尝试操作...
    attempts += 1
    # success = try_operation()

三、while循环的经典模式

3.1 计数器模式

# 模式1:从0到N-1
i = 0
while i < 10:
    print(i, end=' ')
    i += 1
# 输出: 0 1 2 3 4 5 6 7 8 9

# 模式2:从1到N
i = 1
while i <= 10:
    print(i, end=' ')
    i += 1
# 输出: 1 2 3 4 5 6 7 8 9 10

# 模式3:倒数
i = 10
while i > 0:
    print(i, end=' ')
    i -= 1
# 输出: 10 9 8 7 6 5 4 3 2 1

# 模式4:步进(每隔N个)
i = 0
while i < 100:
    print(i, end=' ')
    i += 10
# 输出: 0 10 20 30 40 50 60 70 80 90

# 模式5:指数增长
i = 1
while i < 1000:
    print(i, end=' ')
    i *= 2
# 输出: 1 2 4 8 16 32 64 128 256 512

3.2 哨兵模式

哨兵模式使用一个特殊的值作为终止信号:

# 哨兵模式:用特殊值表示"结束"
SENTINEL = ""   # 空行作为哨兵

print("请输入多行文本(空行结束):")
lines = []
while True:
    line = input()
    if line == SENTINEL:
        break
    lines.append(line)

print(f"共输入 {len(lines)} 行")

# 另一种哨兵模式:数值哨兵
print("\n请输入分数(-1结束):")
scores = []
while True:
    try:
        score = float(input("分数: "))
        if score == -1:
            break
        if 0 <= score <= 100:
            scores.append(score)
        else:
            print("分数应在0-100之间")
    except ValueError:
        print("请输入有效的数字")

if scores:
    print(f"平均分: {sum(scores)/len(scores):.1f}")

3.3 标志(Flag)模式

# 标志模式:用一个布尔变量控制循环
def find_first_even(numbers):
    """找到列表中第一个偶数"""
    found = False
    index = 0
    
    while index < len(numbers) and not found:
        if numbers[index] % 2 == 0:
            found = True
        else:
            index += 1
    
    if found:
        return index, numbers[index]
    else:
        return -1, None

# 更复杂的标志模式
def process_with_retry(operation, max_retries=3):
    """带重试的操作处理"""
    retry_count = 0
    success = False
    result = None
    
    while retry_count < max_retries and not success:
        try:
            result = operation()
            success = True
            print(f"✅ 第 {retry_count + 1} 次尝试成功")
        except Exception as e:
            retry_count += 1
            print(f"❌ 第 {retry_count} 次尝试失败: {e}")
            if retry_count < max_retries:
                print(f"   等待后重试...")
    
    return success, result

3.4 游戏主循环模式

# 经典的游戏主循环
def game_loop():
    """游戏主循环示例"""
    running = True
    score = 0
    level = 1
    
    while running:
        # 渲染
        print(f"\n=== 关卡 {level} === 得分: {score} ===")
        
        # 输入
        action = input("行动 (jump/run/quit): ").strip().lower()
        
        # 更新
        if action == "quit":
            running = False
            print("游戏结束!")
        elif action == "jump":
            score += 10
            print("跳起来!+10分")
        elif action == "run":
            score += 5
            print("跑起来!+5分")
        else:
            print("无效操作")
        
        # 升级检查
        if score >= level * 50:
            level += 1
            print(f"🎉 升级!进入关卡 {level}!")
    
    return score

# 运行
# final_score = game_loop()
# print(f"最终得分: {final_score}")

四、无限循环与break

4.1 while True 的合理使用

# while True 不是bug,而是一种设计模式
# 配合 break 可以创建灵活的循环

# 示例1:菜单循环
def menu_loop():
    while True:
        print("\n=== 主菜单 ===")
        print("1. 新建文件")
        print("2. 打开文件")
        print("3. 保存文件")
        print("4. 退出")
        
        choice = input("请选择: ").strip()
        
        if choice == "1":
            print("📄 新建文件...")
        elif choice == "2":
            print("📂 打开文件...")
        elif choice == "3":
            print("💾 保存文件...")
        elif choice == "4":
            print("👋 再见!")
            break
        else:
            print("无效选择,请重试")

# 示例2:验证循环(直到用户输入合法数据)
def get_valid_number(prompt, min_val=None, max_val=None):
    """获取一个合法的数字输入"""
    while True:
        try:
            value = float(input(prompt))
            if min_val is not None and value < min_val:
                print(f"值不能小于 {min_val},请重新输入")
                continue
            if max_val is not None and value > max_val:
                print(f"值不能大于 {max_val},请重新输入")
                continue
            return value
        except ValueError:
            print("请输入一个有效的数字")

# age = get_valid_number("请输入年龄: ", 0, 150)
# print(f"年龄: {age}")

4.2 多重退出点

# 鸡尾酒会问题:while True + 多个break
def authenticate():
    """用户认证:多种退出条件"""
    max_attempts = 3
    attempts = 0
    
    while True:
        if attempts >= max_attempts:
            print("❌ 尝试次数过多,账户已锁定")
            return False
        
        username = input("用户名: ").strip()
        
        if username.lower() == "quit":
            print("👋 已取消登录")
            return False
        
        if not username:
            print("用户名不能为空")
            continue
        
        password = input("密码: ").strip()
        attempts += 1
        
        if username == "admin" and password == "123456":
            print("✅ 登录成功!")
            return True
        else:
            remaining = max_attempts - attempts
            print(f"❌ 用户名或密码错误(剩余{remaining}次尝试)")

# authenticate()

五、while循环的常见陷阱

5.1 无限循环

# 陷阱1:忘记更新循环变量
# i = 0
# while i < 10:
#     print(i)      # 永远打印0

# 陷阱2:条件永远为True
# while 1 == 1:     # 永远为True
#     pass

# 陷阱3:更新方向错误
# i = 10
# while i > 0:
#     print(i)
#     i += 1         # i越来越大,永远大于0!

# 陷阱4:浮点数精度导致永不相等
x = 0.0
count = 0
while x != 1.0:      # ⚠️ 浮点累积误差!
    x += 0.1
    count += 1
    if count > 20:   # 安全阀!
        print(f"x={x},强制退出")
        break
# 因为0.1在二进制中无法精确表示
# 所以x永远不会恰好等于1.0

# ✅ 改进:使用不等式
x = 0.0
while x < 1.0:
    x += 0.1
print(f"x = {x}")  # x = 1.0999999999999999(仍然不完全等于1.0)

5.2 off-by-one错误

# "差一错误"——最常见的循环bug

# 常见错误:应该用 < 还是 <= ?
# 想要循环5次

# ✅ 方式1:从0开始,用<
count = 0
while count < 5:    # 5次: 0,1,2,3,4
    count += 1

# ✅ 方式2:从1开始,用<=
count = 1
while count <= 5:   # 5次: 1,2,3,4,5
    count += 1

# ❌ 错误:从0开始但用了<=
# count = 0
# while count <= 5:  # 6次! 0,1,2,3,4,5
#     count += 1

# ❌ 错误:从1开始但用了<
# count = 1
# while count < 5:   # 4次! 1,2,3,4
#     count += 1

# 📝 记住公式:
# 从 a 到 b(包含b): while a <= b: a += step
# 从 a 到 b(不包含b): while a < b: a += step
# 循环 N 次: for i in range(N) —— 用for循环避免off-by-one

5.3 循环变量污染

# while循环结束后,循环变量仍然存在
i = 0
while i < 5:
    i += 1

print(i)  # 5 —— i还在作用域中!

# 如果不小心在其他地方复用了同名变量...
# 这可能导致难以发现的bug

def process_data():
    i = 0
    while i < len(data):
        # 处理data[i]
        i += 1
    # i现在是len(data)
    return i  # 可能是你想要的结果,也可能是bug

# 💡 解决:用for循环代替简单的计数循环
# for循环的迭代变量在循环结束后仍然存在
# 但它的语义更清晰——"对每个元素做某事"

六、while vs for:选型指南

# 选型决策表
# 
# 用 while 当:
# - 循环次数未知(取决于条件何时变为False)
# - 需要根据运行时状态决定是否继续
# - 游戏主循环、服务器监听等"永远运行直到被告知停止"
#
# 用 for 当:
# - 循环次数已知(遍历固定范围的数字、列表、字典等)
# - 需要对可迭代对象的每个元素执行操作
# - 计数器循环(range)

# while的典型场景
def read_until_end(file):
    """读取文件直到结束——不知道有多少行"""
    lines = []
    while True:
        line = file.readline()
        if not line:     # 读到文件末尾
            break
        lines.append(line)
    return lines

# for的典型场景
def process_items(items):
    """处理每个元素——知道要遍历什么"""
    for item in items:
        process(item)

七、实战案例

7.1 ATM取款机

class ATM:
    """ATM模拟 —— while循环的完整应用"""
    
    def __init__(self, balance=10000):
        self.balance = balance
    
    def run(self):
        """ATM主循环"""
        print("=" * 40)
        print("欢迎使用ATM自动取款机")
        print("=" * 40)
        
        while True:
            print(f"\n当前余额: ¥{self.balance:,.2f}")
            print("1. 取款  2. 存款  3. 查询  4. 退出")
            
            choice = input("请选择操作: ").strip()
            
            if choice == "1":
                self._withdraw()
            elif choice == "2":
                self._deposit()
            elif choice == "3":
                self._check_balance()
            elif choice == "4":
                print("感谢使用,再见!👋")
                break
            else:
                print("无效选择,请重新输入")
    
    def _withdraw(self):
        """取款操作 —— 验证循环"""
        while True:
            try:
                amount = float(input("请输入取款金额(或0返回): "))
                
                if amount == 0:
                    return
                
                if amount <= 0:
                    print("金额必须大于0")
                    continue
                
                if amount > self.balance:
                    print(f"❌ 余额不足!当前余额: ¥{self.balance:,.2f}")
                    continue
                
                if amount > 5000:
                    confirm = input("单笔超过5000元,确认取款?(y/n): ")
                    if confirm.lower() != 'y':
                        print("已取消取款")
                        return
                
                self.balance -= amount
                print(f"✅ 取款成功!取款: ¥{amount:,.2f}, 余额: ¥{self.balance:,.2f}")
                return
                
            except ValueError:
                print("请输入有效的金额")
    
    def _deposit(self):
        """存款操作"""
        while True:
            try:
                amount = float(input("请输入存款金额(或0返回): "))
                if amount == 0:
                    return
                if amount <= 0:
                    print("金额必须大于0")
                    continue
                
                self.balance += amount
                print(f"✅ 存款成功!存款: ¥{amount:,.2f}, 余额: ¥{self.balance:,.2f}")
                return
            except ValueError:
                print("请输入有效的金额")
    
    def _check_balance(self):
        """查询余额"""
        print(f"💰 当前余额: ¥{self.balance:,.2f}")

# 运行
# atm = ATM(5000)
# atm.run()

7.2 数字猜谜游戏

import random

def guess_number_game():
    """猜数字游戏 —— while循环的经典应用"""
    
    # 游戏设置
    min_num = 1
    max_num = 100
    target = random.randint(min_num, max_num)
    max_attempts = 7
    
    print("=" * 50)
    print(f"🎯 猜数字游戏({min_num}-{max_num})")
    print(f"你有 {max_attempts} 次机会")
    print("=" * 50)
    
    attempts = 0
    guessed = False
    
    while attempts < max_attempts and not guessed:
        remaining = max_attempts - attempts
        print(f"\n剩余机会: {remaining}")
        
        # 输入验证
        while True:
            try:
                guess = int(input(f"请输入你的猜测 ({min_num}-{max_num}): "))
                if min_num <= guess <= max_num:
                    break
                else:
                    print(f"请输入 {min_num} 到 {max_num} 之间的数字")
            except ValueError:
                print("请输入有效的整数")
        
        attempts += 1
        
        # 判断结果
        if guess == target:
            print(f"\n🎉 恭喜!你猜对了!答案就是 {target}!")
            print(f"你用了 {attempts} 次机会")
            guessed = True
        elif guess < target:
            print(f"📈 太小了!往大猜")
        else:
            print(f"📉 太大了!往小猜")
    
    if not guessed:
        print(f"\n😞 很遗憾,机会用完了。答案是 {target}")
    
    # 再玩一次?
    while True:
        again = input("\n再玩一次?(y/n): ").strip().lower()
        if again in ('y', 'yes'):
            return True
        elif again in ('n', 'no'):
            return False
        else:
            print("请输入 y 或 n")

# 游戏循环
# play = True
# while play:
#     play = guess_number_game()
# print("感谢游玩!👋")

八、本章小结

本文我们系统学习了Python while循环的方方面面:

基本结构while 条件: 循环体,三要素——初始化、条件、更新缺一不可。

经典模式

无限循环while True配合break是合法且常用的设计模式,尤其在菜单、输入验证、服务器监听等场景。

常见陷阱:无限循环(条件不更新)、off-by-one错误(边界判断)、浮点精度问题、循环变量污染——知道这些坑才能有效避免。

while vs for:不知道循环次数用while,知道用for。简单的计数循环优先用for。

while循环是编程中最基础也最强大的控制结构之一。掌握好它的各种模式,你就能处理各种需要"重复执行"的场景。⌨️ 下一篇文章,我们将学习while-else的特殊用法——一个很多Python开发者都不知道的特性!

到此这篇关于Python基础指南之while循环的基本结构与使用场景详解的文章就介绍到这了,更多相关Python while循环内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文