别再写烂代码了,Python条件语句与循环的正确姿势

40 阅读9分钟

你有没有过这种经历:

# 很多人的代码(包括三个月前的我)
def check_score(score):
    if score >= 90:
        grade = "A"
    if score >= 80:
        grade = "B"
    if score >= 70:
        grade = "C"
    return grade

然后你发现自己永远只能得到A级,因为不管分数多少,都会被最后一个if覆盖...

更坑的是这样的循环:

# 让人脸黑的代码
students = ["小明", "小红", "小张"]
scores = [85, 92, 78]
for i in range(len(students)):
    for j in range(len(scores)):
        if students[i] == "小红":
            print(f"{students[i]}的分数是{scores[i]}")
            break  # 这个break只跳出内层循环

最后你发现小红只打印了一次,但小明和小张的信息完全丢了...

今天咱们就来彻底搞懂Python的条件语句和循环,让你从此写出让人眼前一亮的代码。

条件语句:不只是if和else那么简单

从C语言思维到Python思维

很多人写Python还带着C语言的阴影:

# C语言风格的Python代码(丑爆了)
if condition == True:
    do_something()
if condition == False:
    do_other()
if len(list) > 0:
    process_list()

Pythonic的写法:

# 优雅的Python风格
if condition:
    do_something()
else:
    do_other()
if my_list:  # 空列表自动为False
    process_list()

记住:Python的if后面跟的是"真值表达式",不是布尔表达式。

什么是真值?简单说:

  • 0, "", [], {}, None, False → 假值
  • 其他一切 → 真值

elif的威力

很多人的条件判断像这样:

# 嵌套地狱
if age < 18:
    print("未成年")
else:
    if age < 30:
        print("年轻人")
    else:
        if age < 50:
            print("中年人")
        else:
            print("老年人")

这就是我说的"金字塔代码",看得人想吐...

正确的姿势:

# 扁平结构,一目了然
if age < 18:
    print("未成年")
elif age < 30:
    print("年轻人")
elif age < 50:
    print("中年人")
else:
    print("老年人")

elif比嵌套if更优雅,性能也更好。因为一旦某个条件满足,就不会继续检查后面的条件。

三元运算符:一行代码的优雅

传统写法:

if score >= 60:
    result = "及格"
else:
    result = "不及格"

Pythonic写法:

result = "及格" if score >= 60 else "不及格"

但别滥用!复杂的判断还是老老实实写if:

# 这样的三元运算符就是灾难
result = "优秀" if score >= 90 else "良好" if score >= 80 else "及格" if score >= 60 else "不及格"

# 不如写成清晰的多行if
if score >= 90:
    result = "优秀"
elif score >= 80:
    result = "良好"
elif score >= 60:
    result = "及格"
else:
    result = "不及格"

循环:让你的代码跑起来

for循环:不是只能range()

很多初学者只知道:

# 最基础的用法
for i in range(10):
    print(i)

但Python的for循环远不止于此:

# 直接遍历列表
fruits = ["苹果", "香蕉", "橙子"]
for fruit in fruits:
    print(f"我喜欢吃{fruit}")

# 同时获取索引和值
for index, fruit in enumerate(fruits):
    print(f"第{index}个水果是{fruit}")

# 遍历字典
person = {"name": "张三", "age": 25, "city": "北京"}
for key, value in person.items():
    print(f"{key}: {value}")

# 反向遍历
for fruit in reversed(fruits):
    print(f"倒序:{fruit}")

while循环:别把自己玩死

新手最容易犯的错误:

# 致命的死循环
count = 0
while count < 10:
    print(count)
    # 忘记count += 1,CPU:我太难了!

正确的写法:

count = 0
while count < 10:
    print(count)
    count += 1  # 记得更新循环条件!

while循环适合不知道具体次数的情况:

# 等待用户输入正确答案
while True:
    answer = input("Python的创始人是谁?")
    if answer.lower() == "guido van rossum":
        print("答对了!")
        break
    else:
        print("再想想...")

break和continue:控制的艺术

break:说走就走

# 找到第一个满足条件的就停止
numbers = [1, 3, 5, 7, 9, 2, 4, 6]
for num in numbers:
    if num % 2 == 0:
        print(f"找到第一个偶数:{num}")
        break
# 输出:找到第一个偶数:2

continue:跳过这一次

# 只要偶数,跳过奇数
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
for num in numbers:
    if num % 2 != 0:
        continue  # 跳过奇数
    print(f"偶数:{num}")
# 输出:偶数:2 4 6 8

else子句:循环的彩蛋

99%的Python程序员都不知道循环还有else子句!

# 寻找素数
for num in range(2, 10):
    for i in range(2, num):
        if num % i == 0:
            print(f"{num}不是素数")
            break
    else:
        # 只有循环正常结束(没有break)才会执行
        print(f"{num}是素数")

else什么时候执行?

  • for循环:遍历完所有元素后执行
  • while循环:条件变为False时执行
  • 如果遇到break,else不会执行

这比使用标志变量优雅多了:

# 传统写法(繁琐)
is_prime = True
for i in range(2, num):
    if num % i == 0:
        is_prime = False
        break
if is_prime:
    print(f"{num}是素数")

# Pythonic写法(简洁)
for i in range(2, num):
    if num % i == 0:
        print(f"{num}不是素数")
        break
else:
    print(f"{num}是素数")

实战场景:让知识落地

场景1:用户权限判断

# 复杂的权限系统
def check_permission(user):
    if not user or not user.get("is_active"):
        return "无权限:用户不存在或已禁用"

    if user.get("role") == "admin":
        return "超级管理员权限"
    elif user.get("role") == "editor":
        if user.get("department") == "tech":
            return "技术编辑权限"
        else:
            return "普通编辑权限"
    elif user.get("level", 0) >= 5:
        return "高级用户权限"
    else:
        return "基础用户权限"

场景2:数据处理流水线

# 处理用户数据
def process_users(users):
    results = []

    for user in users:
        # 跳过无效用户
        if not user or not user.get("email"):
            continue

        # 数据清洗
        cleaned_user = {
            "name": user.get("name", "未知用户").strip(),
            "email": user["email"].lower(),
            "level": user.get("level", 1)
        }

        # 权限判断
        if cleaned_user["level"] >= 5:
            cleaned_user["permission"] = "高级"
        elif cleaned_user["level"] >= 3:
            cleaned_user["permission"] = "中级"
        else:
            cleaned_user["permission"] = "基础"

        results.append(cleaned_user)

    return results

# 使用示例
users = [
    {"name": "张三", "email": "zhangsan@example.com", "level": 6},
    {"name": "  李四  ", "email": "LISI@EXAMPLE.COM", "level": 2},
    {"name": "", "email": "", "level": 1},  # 会被跳过
    {"name": "王五", "email": "wangwu@example.com"}  # 默认level=1
]

processed = process_users(users)
for user in processed:
    print(f"{user['name']} - {user['email']} - {user['permission']}")

场景3:游戏逻辑

# 简单的猜数字游戏
import random

def guess_number_game():
    target = random.randint(1, 100)
    attempts = 0
    max_attempts = 7

    print("我想了一个1-100之间的数字,你有7次机会猜!")

    while attempts < max_attempts:
        try:
            guess = int(input(f"第{attempts + 1}次猜测:"))
            attempts += 1

            if guess == target:
                print(f"🎉 恭喜!你用{attempts}次就猜中了!")
                break
            elif guess < target:
                print("太小了!")
            else:
                print("太大了!")

            # 剩余次数提示
            remaining = max_attempts - attempts
            if remaining > 0:
                print(f"还剩{remaining}次机会")

        except ValueError:
            print("请输入数字!")
            attempts -= 1  # 不计入有效尝试
    else:
        # while循环正常结束(用户没猜中)
        print(f"😅 很遗憾,正确答案是{target}")

# 运行游戏
# guess_number_game()

常见坑爹错误及解决方案

坑1:缩进错误

Python的灵魂是缩进,一个Tab键毁所有:

# 错误示例:缩进不一致
if condition:
    print("条件成立")
    print("这是错误的缩进")

# 正确示例:统一使用4个空格
if condition:
    print("条件成立")
    print("正确的缩进")

建议: 配置编辑器自动将Tab转换为4个空格。

坑2:修改正在遍历的列表

# 致命错误:修改正在遍历的列表
numbers = [1, 2, 3, 4, 5]
for num in numbers:
    if num % 2 == 0:
        numbers.remove(num)  # 这会搞乱迭代器
print(numbers)  # 结果可能是 [1, 3, 5] 或 [1, 2, 3, 5]

# 正确做法:创建新列表或遍历副本
numbers = [1, 2, 3, 4, 5]
odd_numbers = []
for num in numbers:
    if num % 2 != 0:
        odd_numbers.append(num)
print(odd_numbers)  # [1, 3, 5]

# 或者用列表推导式(更Pythonic)
odd_numbers = [num for num in numbers if num % 2 != 0]

坑3:循环变量的作用域

# Python 2.x的坑(在Python 3中已修复)
for i in range(5):
    pass
print(i)  # Python 2中会输出4,Python 3中会报错

# 建议总是显式初始化
i = None
for i in range(5):
    pass
print(i)  # 安全的做法

坑4:忘记else的坑爹逻辑

# 常见错误:以为if-else的else对应for
for item in items:
    if condition(item):
        process(item)
        break
else:
    # 这个else不是if的else,是for的else!
    print("没有找到符合条件的item")

记住:循环的else子句在循环正常结束时执行,不是if的else!

性能优化技巧

技巧1:使用生成器表达式

# 列表推导式(立即创建列表)
squares = [x**2 for x in range(1000000)]  # 占用内存

# 生成器表达式(按需生成)
squares_gen = (x**2 for x in range(1000000))  # 节省内存

# 处理大数据时优先考虑生成器
total = sum(x**2 for x in range(1000000))  # 直接计算,不存储中间结果

技巧2:避免不必要的循环

# 低效做法
result = []
for item in items:
    if item in valid_items:
        result.append(process(item))

# 高效做法
valid_set = set(valid_items)  # 转换为set,查找O(1)
result = [process(item) for item in items if item in valid_set]

技巧3:使用内置函数

# 自己实现的循环
total = 0
for num in numbers:
    total += num

# 使用内置函数
total = sum(numbers)

# 多个条件
# 写法1:多个if
if age >= 18:
    if has_license:
        if not_drunk:
            print("可以开车")

# 写法2:and连接
if age >= 18 and has_license and not_drunk:
    print("可以开车")

# 写法3:all函数(最优雅)
conditions = [age >= 18, has_license, not_drunk]
if all(conditions):
    print("可以开车")

调试技巧:让bug无处可藏

技巧1:print大法

# 调试循环
for i, item in enumerate(items):
    print(f"Debug: i={i}, item={item}, condition={condition(item)}")
    if condition(item):
        process(item)

技巧2:使用断言

def calculate_price(quantity, unit_price):
    assert quantity >= 0, "数量不能为负数"
    assert unit_price >= 0, "单价不能为负数"

    total = quantity * unit_price
    assert total >= 0, "总价计算错误"

    return total

技巧3:分步调试复杂条件

# 复杂条件难以调试
if user and user.is_active and user.level >= 3 and (user.role == "admin" or user.has_permission):

# 分步写法便于调试
if not user:
    print("用户不存在")
elif not user.is_active:
    print("用户未激活")
elif user.level < 3:
    print("用户等级不够")
elif user.role == "admin":
    print("管理员权限")
elif user.has_permission:
    print("特殊权限")
else:
    print("无权限")

总结

记住一句话:代码是写给人看的,顺便给机器执行。

  • 条件语句:保持扁平结构,避免嵌套地狱
  • 循环:善用for遍历,谨慎使用while
  • 控制流:break用于提前退出,continue用于跳过
  • else子句:循环的彩蛋,在循环正常结束时执行
  • 可读性:比炫技更重要,你的同事会感谢你

下次再写条件语句和循环时,想想今天的这篇文章。你的代码不仅会运行正确,还会让人赏心悦目。


你在项目里遇到过什么坑爹的条件或循环问题?评论区聊聊,看看谁的bug更奇葩!