当前位置:首页>python>Python全栈修炼之路 | 第6篇:条件判断与循环控制

Python全栈修炼之路 | 第6篇:条件判断与循环控制

  • 2026-10-11 06:34:50
Python全栈修炼之路 | 第6篇:条件判断与循环控制

作者:还怪好嘞 发布时间:2026-05-25 难度:⭐⭐⭐ 阅读时长:约30分钟


前言

程序的核心能力在于决策与重复。条件判断让程序能够根据不同情况做出不同选择,循环控制则让程序能够高效地处理重复性任务。本文将深入讲解Python中的条件判断与循环控制机制,从基础语法到底层原理,助你写出更优雅、更高效的代码。


一、条件判断:程序的智能决策

1.1 if/elif/else 基础语法

Python的条件判断语法简洁直观,使用缩进来表示代码块。

# 基础条件判断score = 85if score >= 90:    grade = 'A'elif score >= 80:    grade = 'B'elif score >= 70:    grade = 'C'elif score >= 60:    grade = 'D'else:    grade = 'F'print(f"成绩等级: {grade}")  # 输出: 成绩等级: B

关键要点:

  • elif
     是 “else if” 的缩写,可以有多个
  • 条件判断从上到下执行,第一个为True的条件会被执行,其余被跳过
  • 使用4个空格缩进(PEP 8规范)

1.2 条件表达式(三元运算符)

Python支持简洁的条件表达式:

# 传统写法if age >= 18:    status = "成年人"else:    status = "未成年人"# 条件表达式(更简洁)status = "成年人" if age >= 18 else "未成年人"# 嵌套条件表达式(谨慎使用,可读性降低)result = "优秀" if score >= 90 else "良好" if score >= 80 else "及格" if score >= 60 else "不及格"

1.3 match-case 模式匹配(Python 3.10+)

Python 3.10引入了match-case语句,提供更强大的模式匹配能力:

def handle_command(command):    match command:        case "start":            return "启动系统"        case "stop":            return "停止系统"        case "restart":            return "重启系统"        case _:            return f"未知命令: {command}"# 带数据提取的模式匹配def analyze_point(point):    match point:        case (0, 0):            return "原点"        case (x, 0):            return f"x轴上的点,x={x}"        case (0, y):            return f"y轴上的点,y={y}"        case (x, y):            return f"普通点,坐标({x}, {y})"        case _:            return "不是有效的点"print(analyze_point((3, 0)))  # 输出: x轴上的点,x=3

match-case vs if-elif 对比:

特性
if-elif
match-case
版本要求
所有Python版本
Python 3.10+
适用场景
复杂条件判断
数据结构匹配
可读性
条件复杂时较差
模式清晰时更好
性能
逐个条件判断
内部优化,通常更快

二、布尔值的本质

2.1 真值测试规则

在Python中,以下值被视为False:

  • None
  • False
  • 数值零:0, 0.0, 0j
  • 空序列:'', [], (), {}, set(), range(0)

其余所有值都被视为True。

# 真值测试示例values = [0, 1, "", "hello", [], [1, 2], None, True]for v in values:    if v:        print(f"{v!r} 是真值")    else:        print(f"{v!r} 是假值")

2.2 短路求值

Python的and和or运算符使用短路求值:

# and: 第一个为False就返回第一个值,否则返回第二个值result1 = 0 and 100      # 结果: 0result2 = 50 and 100     # 结果: 100# or: 第一个为True就返回第一个值,否则返回第二个值result3 = 0 or 100       # 结果: 100result4 = 50 or 100      # 结果: 50# 实用技巧:设置默认值name = user_input or "匿名用户"

三、循环控制:重复的艺术

3.1 for 循环

Python的for循环用于遍历可迭代对象:

# 遍历列表fruits = ["苹果", "香蕉", "橙子"]for fruit in fruits:    print(fruit)# 使用enumerate获取索引for index, fruit in enumerate(fruits):    print(f"{index}: {fruit}")# 遍历字典student = {"name": "张三", "age": 20, "grade": "A"}for key, value in student.items():    print(f"{key} = {value}")# 同时遍历多个序列names = ["Alice", "Bob", "Charlie"]scores = [85, 92, 78]for name, score in zip(names, scores):    print(f"{name}: {score}")

3.2 while 循环

while循环在条件为True时持续执行:

# 基础while循环count = 0while count < 5:    print(count)    count += 1# 带else的while循环(循环正常结束时执行)attempts = 3while attempts > 0:    password = input("请输入密码: ")    if password == "secret":        print("登录成功!")        break    attempts -= 1else:    print("密码错误次数过多,账户已锁定")

3.3 range() 的惰性求值

range()函数返回一个惰性求值的序列对象,而非列表:

# range() 返回的是 range 对象,不是列表r = range(1000000)print(type(r))  # <class 'range'>print(len(r))   # 1000000# 惰性求值:只在需要时生成值# 内存占用极小,无论范围多大# range的三种用法range(5)        # 0, 1, 2, 3, 4range(1, 6)     # 1, 2, 3, 4, 5range(0, 10, 2) # 0, 2, 4, 6, 8

底层原理:range对象存储的是起始值、终止值、步长三个参数,通过__getitem__方法在访问时动态计算值,因此内存占用恒定为O(1)。

3.4 循环控制语句

# break: 立即退出循环for i in range(10):    if i == 5:        break    print(i)  # 输出: 0, 1, 2, 3, 4# continue: 跳过当前迭代for i in range(5):    if i == 2:        continue    print(i)  # 输出: 0, 1, 3, 4# else: 循环正常完成时执行(未被break中断)for i in range(3):    print(i)else:    print("循环正常结束")  # 会执行for i in range(3):    if i == 1:        breakelse:    print("循环正常结束")  # 不会执行

四、推导式:Pythonic的优雅写法

4.1 列表推导式

# 传统写法squares = []for x in range(10):    squares.append(x ** 2)# 列表推导式squares = [x ** 2 for x in range(10)]# 带条件的列表推导式even_squares = [x ** 2 for x in range(10) if x % 2 == 0]# 结果: [0, 4, 16, 36, 64]# 嵌套列表推导式matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]# 结果: [[1, 2, 3], [2, 4, 6], [3, 6, 9]]

4.2 字典和集合推导式

# 字典推导式word_lengths = {word: len(word) for word in ["apple", "banana", "cherry"]}# 结果: {'apple': 5, 'banana': 6, 'cherry': 6}# 集合推导式unique_lengths = {len(word) for word in ["apple", "banana", "cherry", "date"]}# 结果: {4, 5, 6}# 生成器表达式(惰性求值)sum_of_squares = sum(x ** 2 for x in range(1000000))  # 内存友好

4.3 推导式性能对比

import time# 测试数据data = list(range(100000))# 方法1: 传统for循环def method_loop():    result = []    for x in data:        if x % 2 == 0:            result.append(x * 2)    return result# 方法2: 列表推导式def method_comprehension():    return [x * 2 for x in data if x % 2 == 0]# 方法3: map + filterdef method_map_filter():    return list(map(lambda x: x * 2, filter(lambda x: x % 2 == 0, data)))# 性能测试for name, func in [("Loop", method_loop),                    ("Comprehension", method_comprehension),                   ("Map+Filter", method_map_filter)]:    start = time.time()    for _ in range(100):        func()    print(f"{name}: {time.time() - start:.4f}s")

性能对比结果(典型值):

方法
相对速度
可读性
适用场景
for循环
1.0x
中等
复杂逻辑
列表推导式
1.2-1.5x
高
简单转换+过滤
map/filter
0.8-1.0x
低
已有函数可用

推导式更快的原因:

  1. 在C层面执行迭代,减少Python字节码开销
  2. 避免了append方法的多次调用
  3. 局部变量访问更快

五、实战项目

5.1 猜数字游戏

import randomdef guessing_game():    """猜数字游戏 - 综合应用条件判断和循环"""    secret = random.randint(1, 100)    attempts = 0    max_attempts = 7    print("=" * 40)    print("🎮 欢迎来到猜数字游戏!")    print(f"我想了一个1-100之间的数字,你有{max_attempts}次机会")    print("=" * 40)    while attempts < max_attempts:        try:            guess = int(input(f"\n第{attempts + 1}次尝试,请输入你的猜测: "))            attempts += 1            if guess < 1 or guess > 100:                print("⚠️ 请输入1-100之间的数字!")                continue            if guess < secret:                print("📉 太小了!再大一点")            elif guess > secret:                print("📈 太大了!再小一点")            else:                print(f"\n🎉 恭喜你!用了{attempts}次就猜对了!")                return        except ValueError:            print("⚠️ 请输入有效的数字!")    print(f"\n😢 游戏结束!正确答案是 {secret}")if __name__ == "__main__":    guessing_game()

5.2 九九乘法表

def multiplication_table():    """打印九九乘法表 - 嵌套循环应用"""    print("=" * 60)    print("           九九乘法表")    print("=" * 60)    # 左下角版本    print("\n【左下角版本】")    for i in range(1, 10):        for j in range(1, i + 1):            print(f"{j}×{i}={i*j:2}", end="  ")        print()    # 右上角版本    print("\n【右上角版本】")    for i in range(1, 10):        # 打印前导空格        print("      " * (9 - i), end="")        for j in range(i, 10):            print(f"{i}×{j}={i*j:2}", end="  ")        print()multiplication_table()

5.3 FizzBuzz经典问题

def fizzbuzz(n=100):    """    FizzBuzz问题:    - 3的倍数输出Fizz    - 5的倍数输出Buzz    - 同时是3和5的倍数输出FizzBuzz    """    results = []    for i in range(1, n + 1):        if i % 15 == 0:            results.append("FizzBuzz")        elif i % 3 == 0:            results.append("Fizz")        elif i % 5 == 0:            results.append("Buzz")        else:            results.append(str(i))    return results# 使用推导式的优雅写法def fizzbuzz_elegant(n=100):    return [        "Fizz" * (i % 3 == 0) + "Buzz" * (i % 5 == 0) or str(i)        for i in range(1, n + 1)    ]# 测试print("前20个结果:")print(fizzbuzz(20))print("\n优雅写法结果:")print(fizzbuzz_elegant(20))

5.4 矩阵转置

def transpose_matrix(matrix):    """矩阵转置 - 多种实现方式对比"""    # 方法1: 传统循环    def method_loop(m):        rows, cols = len(m), len(m[0])        result = []        for j in range(cols):            new_row = []            for i in range(rows):                new_row.append(m[i][j])            result.append(new_row)        return result    # 方法2: 列表推导式    def method_comprehension(m):        return [[m[i][j] for i in range(len(m))] for j in range(len(m[0]))]    # 方法3: zip函数(最Pythonic)    def method_zip(m):        return [list(row) for row in zip(*m)]    # 测试    print("原始矩阵:")    for row in matrix:        print(row)    print("\n转置后 (zip方法):")    result = method_zip(matrix)    for row in result:        print(row)    return result# 测试matrix = [    [1, 2, 3],    [4, 5, 6],    [7, 8, 9]]transpose_matrix(matrix)

六、常见陷阱与最佳实践

6.1 陷阱1:循环中的可变默认参数

# ❌ 错误:在循环中修改正在迭代的列表numbers = [1, 2, 3, 4, 5]for n in numbers:    if n % 2 == 0:        numbers.remove(n)  # 危险!会导致跳过元素print(numbers)  # 结果可能不符合预期# ✅ 正确:创建新列表或遍历副本numbers = [1, 2, 3, 4, 5]numbers = [n for n in numbers if n % 2 != 0]  # 推荐# 或for n in numbers[:]:  # 遍历副本    if n % 2 == 0:        numbers.remove(n)

6.2 陷阱2:range的边界问题

# ❌ 容易混淆:range是左闭右开for i in range(1, 5):    print(i)  # 输出 1, 2, 3, 4(不包含5)# ✅ 记忆技巧:range(start, stop) 包含start,不包含stop# range(n) 等价于 range(0, n)

6.3 陷阱3:循环变量泄漏

# Python 3中,循环变量不会泄漏到外部作用域for i in range(5):    passprint(i)  # Python 3中输出 4(最后一次的值)# 但在列表推导式中,变量不会泄漏x = 'before'[y for x in range(5)]print(x)  # 输出 'before'(Python 3中)

6.4 陷阱4:空容器的真值判断

# ❌ 不推荐if len(my_list) == 0:    print("列表为空")# ✅ 推荐:直接使用真值测试if not my_list:    print("列表为空")if my_list:  # 列表非空    print("列表有元素")

6.5 最佳实践总结

场景
推荐做法
避免
遍历序列
for item in itemsfor i in range(len(items))
需要索引
enumerate(items)
手动维护计数器
并行遍历
zip(list1, list2)
使用索引同时遍历
过滤+转换
列表推导式
map
+filter组合
大数据集
生成器表达式
列表推导式

七、本章小结

核心知识点回顾

  1. 条件判断
    :if/elif/else用于分支决策,match-case提供模式匹配能力
  2. 布尔值本质
    :理解真值测试规则,善用短路求值
  3. 循环控制
    :for用于遍历,while用于条件循环
  4. 循环控制语句
    :break退出,continue跳过,else处理正常结束
  5. 推导式
    :列表/字典/集合推导式提供简洁高效的数据处理方式

底层原理要点

  • 布尔值
    :基于__bool__方法的真值测试机制
  • range惰性求值
    :O(1)内存占用,动态计算值
  • 推导式性能
    :C层优化,比等效循环快20-50%

八、课后练习

基础练习

  1. 等级判断器:编写程序,根据输入的百分制成绩输出等级(A:90+, B:80+, C:70+, D:60+, F:60-)

  2. 素数筛选:使用埃拉托斯特尼筛法,找出100以内的所有素数

  3. 列表去重:给定列表[1, 2, 2, 3, 3, 3, 4],使用推导式去重并保持顺序

进阶练习

  1. 打印菱形:编写程序打印如下菱形图案:

       *  *** ************ *****  ***   *
  2. 单词频率统计:给定一段文本,统计每个单词出现的次数(使用字典推导式)

  3. 矩阵乘法:实现两个矩阵的乘法运算

挑战练习

  1. 八皇后问题:使用回溯算法解决八皇后问题,找出所有解法

  2. 推导式性能测试:编写程序对比不同规模数据下,循环、推导式、map/filter的性能差异


参考资源

  • Python官方文档 - 控制流
  • PEP 634 - 结构化模式匹配
  • Python性能优化指南

💡 学习建议:条件判断和循环是编程的基础,建议通过大量练习形成肌肉记忆。特别要掌握推导式的使用,这是写出Pythonic代码的关键。


本文是《Python全栈修炼之路》系列第6篇,持续更新中,欢迎关注专栏获取更多内容!

最新文章

随机文章