☰
Python判断与循环语句:构建程序逻辑的核心
2026/10/12 13:25:46 网站建设 项目流程

day03_判断语句与循环语句

1. 这一关到底在学什么

如果你正在自学编程,翻开任何一本入门教材,基本都会在很靠前的位置碰到判断语句和循环语句。很多初学者容易产生一个误解,觉得既然已经学会了变量、数据类型、运算符,为什么还要专门花一整天去啃这两个看起来不起眼的东西?我的看法是,如果把前面的内容比作认识了砖头、水泥和钢筋,那判断语句和循环语句就是第一次开始真正搭建结构。它们决定了程序能不能“思考”、能不能“重复干活”,这是从写几行玩具代码过渡到解决实际问题的第一道分水岭。

以 Python 为例,判断语句的核心是if、elif、else,循环语句的核心是for和while。语法本身掰着指头数都能数过来,难的是两件事:第一,理解程序执行时的走向是怎么被这些语句改变的;第二,在实际需求里知道该用哪个,怎么组合不出错。整篇文章我会按“先理解为什么,再讲怎么用,最后放实战和排坑”的顺序来写,适合刚学完变量和基础运算符、准备开始接触流程控制的初学者参考,也适合教别人入门时当作备课思路。

我见过不少朋友在这个阶段学得很痛苦,不是因为语法记不住,而是因为脑子里没有一个清晰的模型:程序是怎么从一个条件判断跳到另一个条件的?循环到底是在什么时候退出的?如果你也有这种困惑,我建议你在读这篇文章的时候,旁边放一张纸,每遇到一个例子就手动把执行流程画一遍。这是我在带新人时反复强调的做法,效果比盯着屏幕看十遍都好。

2. 判断语句:给程序装上“岔路口”

2.1 为什么需要判断语句

先想一个最简单的场景:你写了一个程序,要求用户输入一个数字,如果这个数字大于零,就打印“正数”。如果没有判断语句,你只能让程序把输入原样打印出来,或者做统一的运算,但无法根据输入的不同做出不同的响应。这种“根据某种条件选择不同路径”的能力,就是判断语句存在的意义。

生活中到处都是这样的决策过程:出门前看天气,下雨就带伞,不下雨就不带;网购时看价格,超过预算就放弃,没超过就下单。把这些场景翻译成代码,就是if 条件成立: 执行某件事。

Python 的判断语句写法非常接近自然语言:

age = 18 if age >= 18: print("可以办理")

这里的age >= 18是一个布尔表达式,它的结果只有两种可能——True或者False。当结果为True时,缩进的代码块会被执行;如果是False,Python 会跳过这段代码,继续往下走。

提示:if后面那一行的缩进必须一致,通常用 4 个空格。Python 靠缩进来识别代码块,跟很多其他语言用花括号的方式不一样。初学者常犯的毛病是混用空格和 Tab,看起来缩进没问题,运行时直接报错。

2.2if、elif、else的完整组合

实际需求很少只有两种情况,更多的是多分支判断。比如根据成绩分数给出等级:90 分以上是优秀,80 到 90 是良好,60 到 80 是及格,60 以下是需要努力。这种场景用单个if显然不够,需要多个分支协同工作。

score = 85 if score >= 90: grade = "优秀" elif score >= 80: grade = "良好" elif score >= 60: grade = "及格" else: grade = "需要努力" print(grade)

这里面有几个特别重要的细节,初学阶段很容易忽略:

第一,elif是“否则如果”的意思,它必须跟在if或者另一个elif后面,不能单独使用。程序从上往下依次判断,一旦某个条件成立,后面的elif和else就全部不再执行。所以上面这个例子中,当score = 85时,第一个条件score >= 90不满足,继续检查第二个条件score >= 80,成立,执行grade = "良好",然后直接跳出整个判断结构,后面的elif和else都被跳过。

第二,条件的顺序很重要。如果把elif score >= 60放到elif score >= 80前面,那么 85 分会被判成“及格”,因为85 >= 60成立了,程序根本不会继续检查后面的条件。我见过很多人踩这个坑,写出的代码逻辑上完全错了,但语法没有报错,特别难排查。记住一个原则:多个互斥条件放在if/elif链里时,应该先写范围更窄、更具体的条件,再写范围更宽的条件。

第三,else可以省略。如果不需要处理“其他所有情况”,就不必写它。但反过来,只要写了else,就表示“前面所有条件都不满足时执行这里”,它不需要任何条件表达式。

2.3 嵌套判断与布尔运算的配合

有时候条件不是单层的。比如判断一个年份是否为闰年,规则是:能被 4 整除但不能被 100 整除,或者能被 400 整除。这个规则本身就带着逻辑运算符,用and和or可以直接表达:

year = 2024 if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0): print(f"{year} 是闰年") else: print(f"{year} 不是闰年")

这段代码展示了两个知识点:一是逻辑运算符and、or的优先级问题,建议在复杂条件里主动加括号,不要依赖记忆去判断优先级;二是判断语句里的条件表达式也可以是复合布尔表达式,判断语句在意的是最终结果是True还是False。

嵌套判断指的是在一个判断代码块内部再写一层判断。比如登录功能里,先判断用户名是否存在,再判断密码是否正确,这就是典型的嵌套:

username = "admin" password = "123456" if username == "admin": if password == "123456": print("登录成功") else: print("密码错误") else: print("用户名不存在")

嵌套不是不能用,但嵌套层数越多,代码读起来越累。一般超过两层,我就会考虑能不能把条件拆开,用逻辑运算符合并成单层判断,或者提前把不满足条件的情况用return或exit切掉,减少嵌套深度。这也是一个代码风格问题,后面我还会再提。

2.4 条件表达式:一行搞定简单判断

Python 提供了一种简写形式,叫做条件表达式,也常被称为三元表达式。它的结构是:

值1 if 条件 else 值2

当条件成立时,整个表达式的值是值1;不成立时,是值2。比如判断一个数是奇数还是偶数:

num = 7 result = "奇数" if num % 2 == 0 else "偶数"

我平时会在“根据条件给变量赋不同值”这种简单场景下用它,赋值语句写一行就结束,非常清爽。但我不建议在三元表达式里继续嵌套三元表达式,比如值1 if 条件1 else (值2 if 条件2 else 值3)这种写法,虽然语法上合法,可读性却会直线下降,别人维护你的代码时会非常痛苦。简单逻辑用三元表达式,复杂逻辑老老实实写if/elif/else,这是我个人的准则。

2.5 Python 的真值判断细节

初学if时,大家习惯性地把条件写成比较表达式,比如if x > 0。但 Python 里有个非常实用又容易被忽略的特性:任意对象都可以直接放在if后面作为条件,Python 会隐式地把它转换成布尔值。

name = "" if name: print("name 不为空") else: print("name 是空的") items = [1, 2, 3] if items: print("列表有元素")

这里的规则是:空字符串、空列表、空字典、空集合、数字 0、None,这些都是假值,会被当成False来处理;其余大多数对象都是真值,会被当成True。

这个特性写起来很方便,但有一个潜在风险:新手容易误以为if name是在判断“name 是否等于空字符串”,实际上它判断的是“name 转换后的布尔值是否为 True”。大多数时候结果是一致的,但如果你定义了一个自定义类,它的__bool__或__len__方法行为很特殊,这个隐式转换可能会带来意外。入门阶段不需要深究这些,但至少要知道有这回事。

3. 循环语句:让代码学会“重复劳动”

3.1for循环与range()

如果说判断语句是岔路口,那循环语句就是传送带。程序需要反复执行某段代码,比如打印 1 到 100 的数字,不可能手动写一百行print,这时候就该循环出场了。

Python 的for循环和 C 语言风格的for循环不太一样。它更适合理解为“遍历序列中的每一个元素”。序列可以是列表、字符串、元组、字典的键,甚至是range()生成的一段整数序列。

for i in [1, 2, 3]: print(i) for char in "hello": print(char)

range()是for循环最常用的搭档。它有几种用法:

  • range(n):生成从 0 到 n-1 的整数
  • range(start, stop):生成从 start 到 stop-1 的整数
  • range(start, stop, step):按 step 步长生成
for i in range(5): print(i) # 0 1 2 3 4 for i in range(2, 8): print(i) # 2 3 4 5 6 7 for i in range(1, 10, 2): print(i) # 1 3 5 7 9

注意range的结束值是不包含的。很多人刚学时会把范围当成数学里的闭区间,写range(1, 10)以为会包含 10,结果打印到 9 就停了。其实这是 Python 里一个统一的设计惯例,切片、range都遵循左闭右开原则。用惯了之后你会觉得这样很顺手,因为它天然能表达“取前 n 个元素”这类需求。

3.2while循环与循环条件

while循环的结构是:只要条件为真,就一直执行循环体。它和for循环的区别在于,for适合“我知道要遍历几次”的场景,while适合“我不知道具体次数,只知道什么时候该停”的场景。

比如猜数字游戏,用户可以反复猜,直到猜中为止。猜了多少次事先是不确定的,这就是while的典型应用场景。

secret = 42 guess = 0 while guess != secret: guess = int(input("请输入你猜的数字:")) if guess < secret: print("猜小了") elif guess > secret: print("猜大了") print("恭喜猜对了")

写while循环最核心的一个注意点是:必须保证循环过程中条件有变成False的可能,也就是说要有某种方式让循环退出,否则就是死循环。上面这个例子里,如果用户一直猜错,程序会一直运行下去,看起来就像卡死了,实际上是在等待新的输入。

这种“卡死”的状态,很多初学者会误以为是程序崩溃了。区分的方法是看终端里有没有继续输出提示、光标是不是还在等待输入。如果完全卡住没有任何输出,那大概率是进入了死循环。

# 常见死循环示例:忘了在循环体里更新条件变量 count = 0 while count < 10: print(count) # 少了 count += 1

这段代码会一直打印 0,因为count的值从未改变,条件count < 10永远成立。

3.3break、continue和else

循环语句有两个非常实用的控制指令:break和continue。

break的作用是立刻终止当前循环,不再执行循环体里break之后的任何代码,也不再进入下一轮循环。它通常和if搭配使用,用来“提前退出”。

for i in range(100): if i == 10: break print(i) # 打印 0 到 9,到 10 时循环结束

continue的作用是跳过当前这一轮循环中剩下的代码,直接进入下一轮循环。

for i in range(10): if i % 2 == 0: continue print(i) # 打印 1 3 5 7 9,跳过偶数

用生活化的类比:break是你在排队时突然决定不排了,直接离开队伍;continue是轮到你时发现自己没带材料,先跳过这一轮,重新排队等着下一轮。

还有一个容易被忽略的知识点:for或while循环后面可以跟else子句。它的执行时机是:循环正常结束时执行else块;如果循环是因为break跳出的,则else块不会执行。

for n in range(2, 10): for x in range(2, n): if n % x == 0: break else: print(n, "是质数")

这段经典代码利用循环else的特性来判断质数:内层循环如果找到了能整除 n 的数,就break跳过;如果内层循环完整遍历完都没有找到,说明 n 是质数,这时执行else块。这个写法比用标志变量判断简洁很多,建议好好体会一下。

3.4 嵌套循环与执行顺序

循环里面再放循环,就叫嵌套循环。最经典的例子是打印九九乘法表:

for i in range(1, 10): for j in range(1, i + 1): print(f"{j} * {i} = {i * j}\t", end="") print()

执行顺序是:外层循环先取 i=1,然后完整执行一遍内层循环(j 从 1 到 1),内层结束后换行,然后外层循环取 i=2,再完整执行内层循环(j 从 1 到 2),以此类推。

嵌套循环的时间复杂度是内外层次数的乘积,这点在写代码时一定要有意识。如果外层循环 1000 次,内层循环 1000 次,总共就是 100 万次操作。当然对入门案例来说不是问题,但到了写真实项目时,嵌套层数和每次循环里的操作都要仔细评估,不然性能会很差。

我见过一个新手写的代码,里层循环里放了一个非常耗时的数据库查询,外层循环 500 次,结果程序跑了半个多小时都没结束。优化思路很多,比如提前把数据一次性查出来缓存到内存里,把嵌套里的查询移出来,等等。这说明学习循环时不能只满足于语法,还要有性能意识。

3.5 循环里的陷阱:range的惰性特性

在 Python 2 里,range()会直接生成一个真正的列表,如果范围很大,内存占用非常可观。Python 3 做了改进,range()返回的是一个可迭代对象,它并不一次性生成所有数字,而是按需产生下一个数字。这意味着range(1000000000)并不会立刻在内存里创建一个包含十亿个元素的列表,这对内存非常友好。

与之类似的一个概念是生成器。如果你在循环里需要遍历非常大的数据集合,可以考虑用生成器表达式或者yield来按需产生值。入门阶段不必深入,但知道这一点能避免踩到“内存暴涨”的坑。

4. 从语法到实战:几个必练小项目

4.1 猜数字小游戏(综合运用循环与判断)

我强烈建议每个初学者在学完判断和循环后,亲手写一个猜数字游戏。这个项目麻雀虽小,五脏俱全,涵盖了随机数生成、while循环、if/elif/else判断、break退出条件、用户输入处理等关键知识点。

import random target = random.randint(1, 100) count = 0 while True: try: guess = int(input("请输入 1-100 之间的整数:")) except ValueError: print("输入的不是有效数字,请重新输入") continue count += 1 if guess < target: print("猜小了") elif guess > target: print("猜大了") else: print(f"猜对了!一共猜了 {count} 次") break

这个代码里有两个值得注意的地方。第一,while True是一个“永远为真”的循环,所以循环体内必须有break来终止它,否则就死循环了。第二,处理用户输入的时候用了try/except来捕获ValueError,防止用户输入非数字导致程序崩溃。这个习惯在真实项目中非常重要,用户的行为永远不可预测。

写完基本版本之后,我建议你自己扩展几个功能:限制最多猜的次数、猜完一个数字后询问是否继续玩、加一个计分功能。这些扩展会逼着你把判断和循环结合起来用,比单独背语法有用得多。

4.2 计算器里的菜单循环(处理“退出”逻辑)

另一个很好的练习是写一个带菜单的计算器。用户输入 1 执行加法、输入 2 执行减法、输入 3 退出。核心是“菜单要一直显示,直到用户选择退出”,这天然就是while循环的场景。

while True: print("1. 加法") print("2. 减法") print("3. 退出") choice = input("请选择功能:") if choice == "1": a = float(input("请输入第一个数:")) b = float(input("请输入第二个数:")) print(f"结果是:{a + b}") elif choice == "2": a = float(input("请输入第一个数:")) b = float(input("请输入第二个数:")) print(f"结果是:{a - b}") elif choice == "3": print("再见") break else: print("无效选择,请重新输入")

这个例子里展示了一个常见的交互模型:不断读取输入、执行操作、回到菜单。真实项目里的命令行工具、游戏主循环等都是类似的套路。把这段练熟,你会对“事件循环”这个概念有初步的感知。

4.3 累加求和与计数(循环的入门用法)

如果你觉得上面两个项目还有点复杂,可以先从简单的累加开始。计算 1 到 100 的和、统计列表里的偶数个数、找到一组数里的最大值,这些基础的求和与计数问题能帮你建立循环的执行思维。

用for累加求和:

total = 0 for i in range(1, 101): total += i print(total) # 5050

用while做同样的事:

total = 0 i = 1 while i <= 100: total += i i += 1 print(total)

用continue跳过不需要的值:

total = 0 for i in range(1, 101): if i % 2 == 1: continue total += i print(total) # 2+4+6+...+100

这些题目看上去简单,但我建议你不要只是看懂,而是真的动手敲一遍,然后变着花样改条件。它会让你对循环体里每一行代码的执行次数有直觉。

5. 常见报错与调试技巧

5.1 缩进错误

这是初学阶段遇到的最多报错之一。如果缩进不一致,Python 会抛出IndentationError或者TabError。解决方法很简单:统一使用 4 个空格,编辑器里把 Tab 键自动转换成空格。

注意:很多现代编辑器默认会把 Tab 转成空格,但如果你在多个编辑器之间切换,或者复制别人的代码,很容易混入真正的制表符。可以在编辑器设置里开启“显示空白字符”功能,直接在视觉上分辨空格和 Tab。

5.2 无限循环

特征:程序运行时一直没有输出,或者输出内容重复且无法停止。排查方法:检查while循环的条件是否有可能变成False;检查循环体里是否忘了更新条件变量;检查是否用了while True但漏写了break。

5.3 条件判断总是进入同一个分支

这种情况很隐蔽,因为语法完全正确,只是逻辑错了。常见原因有两种:一是条件顺序不对,范围大的条件放在了前面,拦截了后面更具体的条件;二是比较运算符用混了,比如把赋值=当成了比较==。Python 里把赋值写在if条件里会直接报语法错误,所以这类问题主要出在条件设计上。

遇到这种问题时,我的调试习惯是在每个分支的开头加一行print,打印当前进入的分支和当时变量的值。比如:

if score >= 60: print("进入及格分支,score =", score)

通过查看这些输出,就能很快定位是哪一步的逻辑不符合预期。这个技巧很简单,但非常有效。

5.4 调试工具与断点法

除了print大法,Python 自带的调试器pdb也很值得学习。你可以在代码里加入一行import pdb; pdb.set_trace(),程序运行到这一行时会暂停,进入交互式调试模式,可以查看变量值、单步执行。

不过对入门阶段来说,我建议先养成用 print 观察执行流的好习惯。它直观、不需要额外学习成本,等碰到 print 解决不了的复杂问题,再引入调试器也不迟。另一个非常实用的调试技巧是“注释法”:把代码中的某些部分注释掉,缩小问题范围。比如怀疑问题出在循环里的某个计算上,就先注释掉print语句,只保留计算,观察变量怎么变化。

5.5 常见问题速查表

问题现象可能原因排查方向
IndentationError缩进不一致,混用 Tab 和空格显示空白字符,统一为 4 空格
SyntaxError在 if 行if后面缺少冒号检查是否写成if x > 0而漏了:
程序不进入任何分支所有条件都为False,且没有else检查条件表达式和变量值
程序只执行第一个分支条件顺序不当,宽条件拦截了窄条件调整条件顺序,先窄后宽
死循环无法停止循环条件一直为真,或缺少 break检查循环体更新语句和退出分支
打印结果包含最后一项的“下一项”range 结束值不包含检查左闭右开规则

6. 我的一点学习体会

判断语句和循环语句是整个编程学习里少有的“必须亲手练够量才能内化”的知识点。语法可以看一遍就懂,但手感必须通过大量练习才能建立。我碰到过一位初学者,他把if和for的语法倒背如流,但让他写一个“从 1 数到 100 打印偶数”的程序,他想了半天不知道从哪里下手。这说明知识在大脑里还没建立执行模型。我给的解决办法很简单,让他把纸笔拿出来,画出程序每一步的执行轨迹。画过几次之后,这类问题自然就消失了。

归根结底,判断语句是在回答“现在该走哪条路”,循环语句是在回答“这件事要重复多少次”。把它们组合起来,程序才算有了最基础的主干。这一关的内容虽然基础,却决定了你后续学函数、数据结构时能不能顺畅理解。我建议你学完这一章之后,至少完成猜数字游戏的迭代版本,并试着把它扩展成带计分和难度选择的工具,相信我,做完之后你会发现自己对流程控制的理解已经上了一个台阶。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询