学习路径:Python_AIGC · Day 4
控制流是程序的骨架。Python 用简洁优雅的语法实现了强大的条件判断、循环迭代和推导式。
一、条件判断:if / elif / else
Python 没有 switch/case,但 if/elif/else 已经足够灵活。
python
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B" # 85 走这个分支
elif score >= 70:
grade = "C"
else:
grade = "D"
print(grade) # B
条件表达式(三元运算符)
python
age = 20
status = "成年" if age >= 18 else "未成年"
print(status) # 成年
# 可以嵌套,但不建议(可读性差)
tag = "老人" if age > 60 else ("中年" if age > 35 else "青年")
短路求值
Python 的逻辑运算符 and / or 具有短路特性:
python
# or 短路:a 为真则整个表达式为 a,不再计算 b
name = input("输入名字: ") or "匿名用户"
# 如果输入为空字符串(falsy),则返回"匿名用户"
# and 短路:a 为假则整个表达式为 a,不再计算 b
def get_config():
print("读取配置...")
return {"debug": True}
config = None
result = config and get_config() # config 为 None(falsy),短路,不会调用函数
print(result) # None
判断 falsy 值的正确姿势
Python 的 falsy 值:None、0、0.0、""、[]、()、{}、set()、False
python
items = []
# ❌ 不推荐:显式比较
if len(items) > 0:
print("有元素")
# ✅ 推荐:利用隐式布尔转换
if items: # 空列表为 False,非空为 True
print("有元素")
# ✅ 检查 None 时用 is
value = None
if value is None:
print("是 None")
# 区分 None 和 0/空字符串
count = 0 # 有效的计数
if count: # ❌ 0 为 falsy,会被忽略
print(f"计数: {count}")
if count is not None: # ✅ 明确检查 None
print(f"计数: {count}") # 计数: 0
二、循环:for 和 while
for 循环 --- Python 的主力
python
# 遍历可迭代对象
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# enumerate:同时获取索引和值
for idx, fruit in enumerate(fruits, start=1): # start 可自定义起始
print(f"{idx}. {fruit}")
# range:数字序列
for i in range(5): # 0, 1, 2, 3, 4
pass
for i in range(2, 8): # 2, 3, 4, 5, 6, 7
pass
for i in range(0, 10, 2): # 0, 2, 4, 6, 8
pass
# 反向遍历
for i in range(10, 0, -1):
print(i, end=" ") # 10 9 8 7 6 5 4 3 2 1
zip:并行遍历
python
names = ["Alice", "Bob", "Charlie"]
scores = [88, 92, 78]
for name, score in zip(names, scores, strict=True):
print(f"{name}: {score}")
# strict=True 要求长度一致,否则抛 ValueError(Python 3.10+)
while 循环
python
# 典型用法:直到满足条件
import random
target = random.randint(1, 100)
guess = None
attempts = 0
while guess != target:
guess = int(input("猜一个数 (1-100): "))
attempts += 1
if guess < target:
print("小了")
elif guess > target:
print("大了")
print(f"猜对了!用了 {attempts} 次")
break / continue / else 子句
python
# break:提前退出循环
for n in range(2, 20):
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
break # 不是质数,跳出内层循环
else:
# ❗ else 子句:循环没有被 break 时执行
print(f"{n} 是质数")
# continue:跳过当前迭代
for i in range(10):
if i % 2 == 0:
continue # 跳过偶数
print(i, end=" ") # 1 3 5 7 9
# ⚠️ 死循环风险
i = 0
while True:
i += 1
if i > 1000000:
break # 必须确保能退出
🔑 关键点 :
for...else的else在循环正常结束(未被 break)时执行。常用于搜索任务。
三、推导式 --- Python 的灵魂语法
推导式(Comprehension)是 Python 最简洁强大的特性之一。
列表推导式
python
# 基础:new_list = [expression for item in iterable if condition]
squares = [x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
evens = [x for x in range(20) if x % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 双重循环 --- 扁平化
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 带条件的三元表达式
nums = [-2, -1, 0, 1, 2]
labels = ["正" if n > 0 else ("负" if n < 0 else "零") for n in nums]
# ['负', '负', '零', '正', '正']
字典推导式
python
# {key_expr: value_expr for item in iterable}
words = ["hello", "world", "python"]
lengths = {word: len(word) for word in words}
# {'hello': 5, 'world': 5, 'python': 6}
# 条件过滤 + 值变换
scores = {"Alice": 88, "Bob": 55, "Charlie": 72}
passed = {name: score for name, score in scores.items() if score >= 60}
# {'Alice': 88, 'Charlie': 72}
# 键值互换(需确保值可哈希且唯一)
inverse = {v: k for k, v in {"a": 1, "b": 2}.items()}
# {1: 'a', 2: 'b'}
集合推导式
python
nums = [1, 2, 2, 3, 3, 3, 4]
unique_squares = {x ** 2 for x in nums}
# {1, 4, 9, 16} --- 自动去重
⚠️ 性能对比
python
import timeit
# 列表推导式 vs for 循环
setup = "nums = list(range(1000))"
for_loop = """
result = []
for x in nums:
if x % 2 == 0:
result.append(x ** 2)
"""
comprehension = """
result = [x ** 2 for x in nums if x % 2 == 0]
"""
print(timeit.timeit(for_loop, setup, number=10000)) # ~0.45s
print(timeit.timeit(comprehension, setup, number=10000)) # ~0.30s ✅ 快 30-40%
推导式更快:因为底层用 C 级别的循环代替了 Python 字节码的逐条执行。
四、实战:FizzBuzz + 控制流综合
python
# 经典 FizzBuzz --- 控制流全家桶
def fizzbuzz(n: int) -> list[str]:
"""1 到 n,3的倍数→Fizz,5的倍数→Buzz,同时→FizzBuzz"""
result = []
for i in range(1, n + 1):
if i % 15 == 0: # 等效 i % 3 == 0 and i % 5 == 0
result.append("FizzBuzz")
elif i % 3 == 0:
result.append("Fizz")
elif i % 5 == 0:
result.append("Buzz")
else:
result.append(str(i))
return result
# 一行版(不推荐生产用)
fizzbuzz_oneliner = [
"FizzBuzz" if i % 15 == 0 else "Fizz" if i % 3 == 0 else "Buzz" if i % 5 == 0 else str(i)
for i in range(1, 101)
]
print(fizzbuzz(15))
# ['1', '2', 'Fizz', '4', 'Buzz', 'Fizz', '7', '8', 'Fizz', 'Buzz', '11', 'Fizz', '13', '14', 'FizzBuzz']
📝 避坑指南
| 陷阱 | 说明 | 正确做法 |
|---|---|---|
is 和 == 混用 |
is 比较身份,== 比较值 |
判 None 用 is,其他用 == |
| 修改遍历中的列表 | 遍历时增删元素导致意外行为 | 遍历副本 list[:] 或新建列表 |
| 推导式嵌套过深 | 可读性急剧下降 | 超过两层循环改用普通 for |
else 子句误解 |
以为 for...else 的 else 是「否则」 |
实际是「没被 break 时执行」 |
python
# ❌ 遍历时删除
items = [1, 2, 3, 4, 5]
for item in items:
if item % 2 == 0:
items.remove(item) # 跳过元素!
print(items) # [1, 3, 5] --- 看起来对了?试试 [1, 2, 2, 3, 4] 就翻车
# ✅ 正确做法
items = [1, 2, 3, 4, 5]
items = [x for x in items if x % 2 != 0] # 重建
Day 4 总结 :控制流是代码的骨架。重点是掌握
for...else的语义、推导式的性能优势、短路求值的妙用,以及常见的遍历陷阱。