当我们掌握了基本数据类型和容器后,下一步就是让代码真正“动起来”。条件分支决定程序走哪条路,循环决定它如何反复处理数据,而推导式则体现了 Python 在表达上的简洁与高效。
这一节会从最基础的 if、for、while 出发,再逐步过渡到推导式、enumerate、zip 等常用增强写法,帮助你把“能写”进一步变成“写得清楚、写得顺手”。
条件分支:if / elif / else
流程控制里最先接触到的,通常就是条件分支。它的核心问题其实非常简单:在不同条件下,程序到底应该走哪条路径。
Python 中最常见的条件结构就是:
score = 85
if score >= 90:
print("A")
elif score >= 60:
print("Pass")
else:
print("Fail")这里最需要尽早建立的两个习惯分别是:
- 条件分支判断的是语义,而不是单纯堆很多表达式;
- 分支顺序很重要,越具体、越优先的条件通常应该放在前面。
很多初学者在写 if 时,容易掉进两个坑。
第一个坑是把条件写得太散。比如明明是在判断用户状态,却把不同字段、不同语义的判断全揉在一层里,结果逻辑越来越难读。第二个坑是分支顺序写反。比如先写一个很宽泛的条件,后面更具体的条件就永远走不到了。
所以,条件分支真正重要的不是语法本身,而是问清楚:
- 我到底在区分哪几种情况?
- 这些情况有没有优先级?
- 哪些条件是互斥的,哪些是补充判断?
另外,Python 里的条件判断不一定非要和显式布尔值绑定。只要某个对象能参与真值判断,它就可以直接进入 if:
name = ""
if name:
print("has name")
else:
print("empty")这和上一节讲到的真值规则是连在一起的。只不过这里也要提醒一句:写得简洁很好,但不要把“值为空”和“值不存在”混为一谈。必要的时候,还是要明确判断 is None 或长度是否为 0。
所以,if / elif / else 看起来是最普通的语法,但它其实是在训练你一件更重要的事:把问题拆成清晰的分支结构。
循环语句:for 与 while
条件分支解决的是“往哪走”,而循环解决的是“做多少次”。当你需要重复处理一批数据、重复执行某个动作时,循环就会成为最自然的表达方式。
Python 里最常见的循环有两种:
for:更适合遍历一批已有数据;while:更适合在某个条件持续成立时反复执行。
先看 for:
items = ["python", "fastapi", "sqlalchemy"]
for item in items:
print(item)对 Python 来说,for 并不只是“从 0 循环到 N”,而更像是“把一个可迭代对象里的元素一个个拿出来处理”。这也是为什么它在列表、元组、字典、集合、字符串等场景下都会非常常见。
而 while 更像“条件驱动”的循环:
count = 0
while count < 3:
print(count)
count += 1它适合表达“只要某个条件还成立,就继续执行”。比如轮询、重试、等待条件变化等场景,while 都会比较自然。
不过,对于大多数初学阶段的代码来说,for 往往比 while 更安全也更清晰。因为 while 如果忘了更新条件,很容易写出死循环:
while True:
...死循环本身不是错,很多服务程序本来就是长期运行的。但如果你只是想写一个普通逻辑,却不小心让条件永远成立,那问题就会非常直接。
所以,一个很实用的经验是:
- 能用
for描述“遍历数据”时,优先用for; - 只有当问题本质上是“条件持续成立就继续执行”时,再考虑
while。
break、continue 与 else
循环里还有几个非常常见的关键字:
break:提前结束整个循环;continue:跳过本轮,直接进入下一轮;else:当循环正常结束而不是被break中断时执行。
先看 break 和 continue:
for num in [1, 2, 3, 4]:
if num == 3:
break
print(num)for num in [1, 2, 3, 4]:
if num % 2 == 0:
continue
print(num)它们的作用很明确,但使用时也要有一个边界意识:如果一个循环里连续出现很多 break 和 continue,往往说明这段逻辑已经开始变得难读,可能需要拆成更清晰的条件结构或函数。
至于循环里的 else,它算是 Python 里一个比较特别的写法。很多人第一次看到都会疑惑:“循环为什么还能接 else?”
你可以把它理解成:
- 如果循环是正常跑完的,就执行
else; - 如果循环中途被
break打断,就不执行else。
例如:
for item in [1, 2, 3]:
if item == 5:
break
else:
print("not found")这类写法在“查找是否命中”场景里会比较自然,但如果你觉得可读性不够强,也完全可以改写成更显式的方式。还是那句话:Pythonic 不等于越特殊越好,而是越贴合问题越好。
推导式入门:让表达更紧凑
当你开始熟悉循环之后,就会遇到 Python 很有代表性的表达能力之一:推导式。
推导式的本质,其实可以理解为:把“遍历 + 处理 + 生成新结构”压缩成一行更紧凑的表达。
比如,我们想把一组数字都乘以 2:
nums = [1, 2, 3]
doubled = [num * 2 for num in nums]和先写空列表、再循环追加相比,推导式会更紧凑,也更符合“我要生成一个新结构”的语义。
但这里有一个非常重要的前提:推导式适合简单、单一、可一眼看清的转换逻辑。
一旦逻辑变复杂,比如嵌套多层条件、多重循环或带有副作用操作,推导式就很容易从“优雅”变成“难读”。所以学推导式,不只是学会写,更是学会什么时候应该收手。
列表推导式
列表推导式是最常见的一种推导式。典型写法包括:
nums = [1, 2, 3, 4]
evens = [num for num in nums if num % 2 == 0]它可以很自然地表达:
- 从原集合里筛选部分元素;
- 对每个元素做变换;
- 最终得到一个新的列表。
如果你发现自己在写这样的模板:
result = []
for item in items:
result.append(...)那往往就可以停下来想一下:这里是不是可以改写成列表推导式?
当然,也不是所有 append 都必须改成推导式。关键仍然是可读性。如果循环体里已经包含复杂判断或多步处理,普通循环依然可能更清楚。
字典与集合推导式
除了列表,字典和集合也都有自己的推导式形式。
字典推导式适合“生成键值映射”:
nums = [1, 2, 3]
squares = {num: num * num for num in nums}集合推导式适合“生成去重后的结果集合”:
words = ["Python", "python", "FastAPI"]
lowered = {word.lower() for word in words}它们背后的思路和列表推导式其实是一致的,区别只在于最终目标结构不同。
所以,推导式真正值得掌握的不是“语法模板有多少种”,而是看见一个场景时,你能否意识到:这里本质上是在生成一个新集合结构,而不是在执行一堆命令式步骤。
enumerate、zip 与循环增强
当你开始熟悉循环之后,很快就会遇到两个特别实用的小工具:enumerate 和 zip。
先看 enumerate。它的作用,是在遍历元素的同时,把索引也一起带出来:
items = ["a", "b", "c"]
for index, item in enumerate(items):
print(index, item)这比自己手动维护计数器更清楚,也更不容易出错。只要你既需要元素本身,又需要它的位置,enumerate 基本都值得优先考虑。
再看 zip。它的作用,是把多个可迭代对象按位置配对:
names = ["Colin", "Alice"]
scores = [95, 88]
for name, score in zip(names, scores):
print(name, score)只要你需要“并排处理两组数据”,zip 就会非常自然。它的优势是能把“这两个列表本来就是一一对应关系”清楚地表达出来,而不是靠索引硬凑。
所以,enumerate 和 zip 其实都属于“让循环更语义化”的工具:
enumerate解决“元素 + 索引”;zip解决“多组数据并排遍历”。
它们本身并不复杂,但会显著改善代码的表达质量。
什么时候该写得更直接一些?
学到这里,很容易出现一个新的倾向:既然 Python 提供了这么多简洁写法,那是不是应该尽量把代码写得越短越好?
答案其实是否定的。
Python 鼓励简洁,但简洁从来不是目标本身。真正的目标始终是:让代码更清楚地表达问题。
所以,一个非常重要的判断标准是:
- 如果一行推导式能让逻辑一眼看明白,那很好;
- 如果一行推导式让你必须停下来反复数括号、读条件、想顺序,那它就已经开始过度了。
比如下面这种简单场景,推导式很合适:
evens = [num for num in nums if num % 2 == 0]但如果你开始写多重嵌套、多个条件、再混入复杂函数调用,那么普通循环往往反而更清楚。
这背后其实对应的是一个更长期的编码判断:不要为了展示“我会这个语法”而牺牲可读性。
代码最终不是写给解释器看的,解释器什么都能读;代码更重要的读者,其实是未来的自己和团队里的其他人。
所以,真正成熟的写法不是“能不能写得更短”,而是“哪种写法最能把当前问题表达清楚”。这也是我们后面讲函数、模块和工程结构时会不断回到的原则。
总结与预告
这一节我们让数据和逻辑真正“动”了起来,掌握了条件判断、循环结构以及 Python 很有代表性的推导式写法。写法只是表层,更重要的是开始学会用更合适的结构表达问题。
下一节我们会继续向“代码组织”迈进,把零散逻辑抽成函数,系统理解参数、返回值与作用域。