====== 第二章 控制流 ======
===== 本章概要 =====
控制流是编程的核心概念,它决定了程序执行的顺序和路径。本章将深入学习Python中的条件语句、循环结构和推导式,让你能够编写更复杂的程序逻辑。
===== 2.1 条件语句 =====
==== 2.1.1 if 语句 ====
最基本的条件语句,当条件为真时执行代码块。
age = 18
if age >= 18:
print("你已经成年了")
==== 2.1.2 if-else 语句 ====
提供两个执行分支。
age = 16
if age >= 18:
print("你已经成年了")
else:
print("你还未成年")
==== 2.1.3 if-elif-else 语句 ====
处理多个条件。
score = 85
if 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}")
==== 2.1.4 嵌套条件语句 ====
在条件语句内部再写条件语句。
age = 25
has_id = True
if age >= 18:
if has_id:
print("可以进入")
else:
print("请出示证件")
else:
print("未成年人禁止进入")
==== 2.1.5 三元表达式 ====
简洁的条件表达式。
age = 20
status = "成年" if age >= 18 else "未成年"
print(status) # 成年
# 等效于
if age >= 18:
status = "成年"
else:
status = "未成年"
==== 2.1.6 条件判断的真值 ====
以下值被视为 ``False``:
# 假值
False
None
0
0.0
0j # 复数0
"" # 空字符串
[] # 空列表
{} # 空字典
() # 空元组
set() # 空集合
# 示例
name = ""
if not name:
print("名字不能为空")
items = []
if not items:
print("列表为空")
==== 2.1.7 逻辑组合条件 ====
# and - 两个条件都满足
age = 25
income = 5000
if age >= 18 and income >= 3000:
print("符合贷款条件")
# or - 任一条件满足
weekend = True
holiday = False
if weekend or holiday:
print("今天休息")
# not - 条件取反
is_closed = False
if not is_closed:
print("商店营业中")
# 组合使用
x = 15
if (x > 10 and x < 20) or x == 0:
print("x在10到20之间,或x等于0")
==== 2.1.8 match-case 结构(Python 3.10+) ====
结构模式匹配,类似于其他语言的switch语句。
def http_status(status):
match status:
case 200:
return "OK"
case 404:
return "Not Found"
case 500:
return "Server Error"
case _:
return "Unknown Status"
# 带守卫子句的匹配
def describe_number(n):
match n:
case 0:
return "零"
case x if x > 0:
return f"正数: {x}"
case x if x < 0:
return f"负数: {x}"
# 匹配数据结构
def handle_command(command):
match command:
case ["load", filename]:
print(f"加载文件: {filename}")
case ["save", filename]:
print(f"保存文件: {filename}")
case ["quit"]:
print("退出程序")
case _:
print("未知命令")
handle_command(["load", "data.txt"])
===== 2.2 循环语句 =====
==== 2.2.1 while 循环 ====
当条件为真时重复执行代码块。
# 基本while循环
count = 0
while count < 5:
print(f"计数: {count}")
count += 1
print("循环结束")
=== while-else 结构 ===
当循环正常结束时(没有被break),执行else块。
# 查找列表中的第一个负数
numbers = [1, 2, 3, 4, 5]
i = 0
while i < len(numbers):
if numbers[i] < 0:
print(f"找到负数: {numbers[i]}")
break
i += 1
else:
print("列表中没有负数")
=== 无限循环 ===
# 用户输入直到输入'quit'
while True:
command = input("请输入命令 (quit退出): ")
if command.lower() == "quit":
print("程序退出")
break
print(f"执行命令: {command}")
==== 2.2.2 for 循环 ====
遍历序列或其他可迭代对象。
# 遍历列表
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# 遍历字符串
for char in "Python":
print(char, end=" ") # P y t h o n
# 遍历字典
student = {"name": "Alice", "age": 20, "grade": "A"}
for key in student:
print(f"{key}: {student[key]}")
# 遍历键值对
for key, value in student.items():
print(f"{key}: {value}")
=== range() 函数 ===
生成数字序列。
# range(stop)
for i in range(5):
print(i, end=" ") # 0 1 2 3 4
# range(start, stop)
for i in range(2, 6):
print(i, end=" ") # 2 3 4 5
# range(start, stop, step)
for i in range(0, 10, 2):
print(i, end=" ") # 0 2 4 6 8
# 倒序
for i in range(10, 0, -1):
print(i, end=" ") # 10 9 8 7 6 5 4 3 2 1
=== enumerate() 函数 ===
同时获取索引和值。
fruits = ["apple", "banana", "cherry"]
# 使用enumerate
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# 指定起始索引
for index, fruit in enumerate(fruits, start=1):
print(f"{index}. {fruit}")
=== zip() 函数 ===
并行遍历多个序列。
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["北京", "上海", "广州"]
for name, age, city in zip(names, ages, cities):
print(f"{name}, {age}岁, 来自{city}")
# zip对象可以转换为列表/字典
pairs = list(zip(names, ages))
print(pairs) # [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
==== 2.2.3 循环控制语句 ====
=== break 语句 ===
立即退出循环。
# 查找第一个大于10的数
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
for num in numbers:
if num > 10:
print(f"找到: {num}")
break
=== continue 语句 ===
跳过当前迭代,继续下一次循环。
# 打印奇数
for i in range(10):
if i % 2 == 0:
continue
print(i, end=" ") # 1 3 5 7 9
=== pass 语句 ===
占位符,不做任何事情。
# 待实现的函数
def future_function():
pass # 稍后实现
# 空的循环体
for i in range(10):
pass # 暂不处理
=== 嵌套循环 ===
# 打印乘法表
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j:2d}", end=" ")
print()
# 遍历二维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for row in matrix:
for item in row:
print(item, end=" ")
print()
==== 2.2.4 循环中的else子句 ====
# 查找质数
for n in range(2, 20):
for x in range(2, n):
if n % x == 0:
print(f"{n} = {x} * {n//x}")
break
else:
# 循环没有被break,说明是质数
print(f"{n} 是质数")
===== 2.3 推导式 =====
推导式(Comprehension)是Python特有的简洁语法,用于从可迭代对象创建新的数据结构。
==== 2.3.1 列表推导式 ====
基本语法:
[表达式 for 变量 in 可迭代对象 if 条件]
示例:
# 创建平方数列表
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件的列表推导式
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 处理字符串
words = ["Hello", "World", "Python", "Programming"]
lengths = [len(word) for word in words]
print(lengths) # [5, 5, 6, 11]
# 嵌套列表推导式
matrix = [[i*j for j in range(1, 4)] for i in range(1, 4)]
print(matrix) # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
# 展平嵌套列表
nested = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [item for sublist in nested for item in sublist]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
==== 2.3.2 字典推导式 ====
# 基本语法:{键: 值 for 变量 in 可迭代对象}
# 创建平方数字典
squares_dict = {x: x**2 for x in range(6)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 交换键值
original = {"a": 1, "b": 2, "c": 3}
swapped = {v: k for k, v in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}
# 过滤字典
scores = {"Alice": 85, "Bob": 92, "Charlie": 78, "David": 95}
passed = {k: v for k, v in scores.items() if v >= 80}
print(passed) # {'Alice': 85, 'Bob': 92, 'David': 95}
==== 2.3.3 集合推导式 ====
# 基本语法:{表达式 for 变量 in 可迭代对象}
# 创建平方集合
squares_set = {x**2 for x in range(20)}
print(squares_set) # 去重后的平方数
# 从字符串创建集合
chars = {c.lower() for c in "Hello World" if c.isalpha()}
print(chars) # {'h', 'e', 'l', 'o', 'w', 'r', 'd'}
==== 2.3.4 生成器表达式 ====
与列表推导式类似,但返回生成器对象,惰性求值,节省内存。
# 生成器表达式
squares_gen = (x**2 for x in range(1000000))
# 逐个获取值
print(next(squares_gen)) # 0
print(next(squares_gen)) # 1
# 在循环中使用
for square in (x**2 for x in range(10)):
print(square, end=" ") # 0 1 4 9 16 25 36 49 64 81
# 与sum()等函数配合使用
total = sum(x**2 for x in range(1000))
print(f"\n0到999的平方和: {total}")
==== 2.3.5 推导式 vs 循环 ====
比较:
# 传统循环方式
evens = []
for x in range(20):
if x % 2 == 0:
evens.append(x)
# 列表推导式(更简洁、更快)
evens = [x for x in range(20) if x % 2 == 0]
何时使用推导式:
* 逻辑简单、可读性好
* 需要创建新的数据结构
* 性能要求高
何时使用循环:
* 逻辑复杂
* 需要执行副作用(如打印、文件操作)
* 需要多行代码完成
===== 2.4 代码示例 =====
==== 示例1:猜数字游戏 ====
import random
secret = random.randint(1, 100)
attempts = 0
max_attempts = 7
print("猜数字游戏!我想了一个1到100之间的数字。")
while attempts < max_attempts:
guess = int(input(f"第{attempts + 1}次尝试,请输入你的猜测: "))
attempts += 1
if guess < secret:
print("太小了!")
elif guess > secret:
print("太大了!")
else:
print(f"恭喜你猜对了!答案就是{secret}。")
print(f"你用了{attempts}次猜中。")
break
else:
print(f"游戏结束!正确答案是{secret}。")
==== 示例2:斐波那契数列 ====
def fibonacci(n):
"""生成前n个斐波那契数"""
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 打印前20个斐波那契数
print("斐波那契数列:")
for i, num in enumerate(fibonacci(20), 1):
print(f"F({i}) = {num}")
==== 示例3:文本分析器 ====
text = """
Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。
Python由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年。
Python源代码遵循GPL协议。
"""
# 统计字符
char_count = len(text)
print(f"总字符数: {char_count}")
# 统计单词
words = text.split()
word_count = len(words)
print(f"单词数: {word_count}")
# 统计行数
lines = text.strip().split('\n')
line_count = len(lines)
print(f"行数: {line_count}")
# 统计每个字符出现的频率(只统计字母)
from collections import Counter
letters = [c.lower() for c in text if c.isalpha()]
frequency = Counter(letters)
print("\n字符频率(前10):")
for char, count in frequency.most_common(10):
print(f" {char}: {count}")
===== 2.5 练习题 =====
==== 练习1:九九乘法表 ====
使用嵌套循环打印九九乘法表。
# 参考答案
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j:2d}", end=" ")
print()
==== 练习2:判断质数 ====
编写函数判断一个数是否为质数。
# 参考答案
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
# 测试
for num in range(1, 101):
if is_prime(num):
print(num, end=" ")
==== 练习3:列表去重并排序 ====
使用集合推导式去除列表中的重复元素并排序。
# 参考答案
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
# 方法1:使用集合推导式
unique_sorted = sorted({x for x in numbers})
print(unique_sorted) # [1, 2, 3, 4, 5, 6, 9]
# 方法2:使用dict.fromkeys()(保持插入顺序)
unique_ordered = list(dict.fromkeys(numbers))
print(unique_ordered) # [3, 1, 4, 5, 9, 2, 6]
==== 练习4:打印金字塔 ====
编写程序打印金字塔图案。
# 参考答案
def print_pyramid(height):
for i in range(height):
spaces = " " * (height - i - 1)
stars = "*" * (2 * i + 1)
print(spaces + stars)
print_pyramid(5)
# 输出:
# *
# ***
# *****
# *******
# *********
==== 练习5:回文检查 ====
编写函数检查字符串是否为回文。
# 参考答案
def is_palindrome(s):
# 去除非字母数字字符并转为小写
cleaned = ''.join(c.lower() for c in s if c.isalnum())
return cleaned == cleaned[::-1]
# 测试
test_strings = ["A man a plan a canal Panama", "Hello", "racecar", "12321"]
for s in test_strings:
print(f"'{s}' -> {is_palindrome(s)}")
===== 本章小结 =====
本章学习了Python的控制流语句:
* **条件语句** - if、elif、else、三元表达式、match-case
* **循环语句** - while、for、range、enumerate、zip
* **循环控制** - break、continue、pass、else子句
* **推导式** - 列表、字典、集合推导式,生成器表达式
掌握控制流后,你可以编写具有复杂逻辑的Python程序了。下一章将学习函数,让代码更加模块化和可重用。
===== 进一步阅读 =====
* [[https://docs.python.org/zh-cn/3/tutorial/controlflow.html|Python官方教程 - 控制流]]
* [[https://docs.python.org/zh-cn/3/reference/compound_stmts.html|复合语句参考]]