news 2026/10/13 21:51:12

让代码学会“看情况办事”:Python分支与循环精讲

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
让代码学会“看情况办事”:Python分支与循环精讲

程序这东西,很多初学者刚接触的时候都会有一个错觉:程序不就是从上到下、一行一行按顺序执行吗?这说的没错,但那只是最基础的顺序结构。真实世界里没有哪款软件是纯直线跑下来的——你点外卖时,程序要根据订单金额判断要不要收配送费;你登录账号时,程序要根据你输入的密码判断对不对;你刷短视频时,程序要根据你的点击行为决定给你推什么内容。这些"根据条件做不同处理"的能力,靠的就是分支和循环。没错,这一讲要聊的,就是编程里怎么让代码"长脑子"。

这一讲是系列教程的第三讲,前两讲应该已经把变量、数据类型、输入输出这些地基打好了。如果你还没掌握那些内容,建议先回去复习一下,因为今天讲的分支和循环,本质上就是把前面那些基础语法串起来的"骨架"。我会用大量贴近实际场景的例子,带你把 if、else、elif、while、for 这几个核心关键字彻底吃透。全程我会用 Python 作为演示语言,它的语法最接近自然语言,初学阶段不会被语法细节绊住脚。

1. 分支的本质:让程序学会"看情况办事"

1.1 从"线性执行"到"条件跳转"

先想一个最基本的问题:顺序执行的代码,就像一条单行道,不管前面是畅通还是堵车,都得一路开到底。而分支结构相当于在这条路上开了几个岔路口,程序运行到岔路口时,会先停下来看一眼"路况",再决定往哪条路走。

这个"看路况"的动作,在编程里叫条件判断。判断的结果只有两种:成立或不成立,也就是 True 或 False。听起来很简单对吧?但几乎所有复杂的业务逻辑,最终都可以拆解成无数个这样的小判断组合。

我举个特别直白的例子。假设你要写一个程序,根据用户输入的年龄判断他属于哪个年龄段:

age = int(input("请输入你的年龄:")) if age < 18: print("未成年人") else: print("成年人")

这段代码运行到if age < 18这一行时,程序会先计算age < 18这个表达式的值。如果用户输入的是 15,这个表达式的结果就是 True,程序走第一个分支,打印"未成年人";如果用户输入的是 20,表达式结果是 False,程序走 else 分支,打印"成年人"。

你发现没有,整个过程中代码"绕了一下路"。这就是分支的意义——不是所有代码都要被执行,而是根据条件选择性地执行其中一部分。用一句人话总结:分支让代码有了选择权。

1.2 布尔值与比较运算:判断的地基

刚才说到条件判断的结果是 True 或 False,这两个值在编程里专门有个名字,叫布尔值(bool)。它们是一切分支判断的基石。

布尔值从哪来?最常见的就是通过比较运算产生。比如:

运算含义示例结果
==相等5 == 5True
!=不相等5 != 3True
>大于7 > 3True
<小于7 < 3False
>=大于等于5 >= 5True
<=小于等于5 <= 4False

这里有个初学者最容易踩的坑:==和=是完全不同的东西。=是赋值,是"把右边的值装进左边的变量";==是比较,是"判断左右两边是否相等"。很多人一上来就把 if 语句写成if age = 18,然后程序直接报错或者出现诡异逻辑,问题就在这。

除了比较运算,还有一种生成布尔值的方式就是逻辑运算——and、or、not。这三个词的意思跟日常英语几乎一样:

  • a and b:a 和 b 同时为 True,结果才是 True
  • a or b:a 和 b 只要有任意一个为 True,结果就是 True
  • not a:把 True 变成 False,把 False 变成 True

举个例子,你想判断一个人是否可以买成人票且不是老年人(假设老年指 65 岁以上):

if age >= 18 and age < 65: print("可以购买全价成人票")

这个逻辑用一句大白话翻译就是:年龄不小于 18,并且年龄小于 65,两个条件同时满足才成立。逻辑运算最实用的地方在于,它能把多个判断条件组合成一个更复杂的判断,让分支结构真正处理现实世界中那些并不简单的规则。

2. if 家族的三种形态:单分支、双分支、多分支

2.1 最基础的 if:不需要 else 的"单行道闸机"

有些场景下,你只需要在条件成立时做某件事,条件不成立时什么都不做,这时候单分支的 if 就够了。

比如说,一个网上商城系统,当订单金额超过一定数额时,就给用户免运费:

total = float(input("请输入订单金额:")) if total >= 99: print("恭喜!已为您免去运费。") print("订单处理完成。")

注意这个例子里,print("订单处理完成。")这行没有缩进,它不属于 if 语句块,不管条件成立与否都会执行。而真正属于 if 的,只有print("恭喜!已为您免去运费。")这一行。

这儿必须强调一下 Python 一个极其重要的语法特点:缩进就是代码块的分界。在 C、Java 这些语言里,代码块用花括号{}包裹;在 Python 里,同一个缩进层级的就是同一个代码块。这一设计让 Python 代码读起来特别清爽,但也让很多新手在这个地方翻车。

我自己见过太多次这样的报错了:

IndentationError: expected an indented block after 'if' statement

翻译过来就是:if 语句后面必须有一个缩进的代码块。换句话说,if 下面不能什么都不写。如果你暂时还没想好条件下该做什么,可以用pass占位,它表示"什么都不做":

if total >= 99: pass # 后续再补充免邮逻辑

2.2 if-else:非此即彼的"岔路口"

双分支比单分支多了一个 else,代表"条件不成立时走另一条路"。它的执行流程非常好理解:if 的条件是 True,执行 if 下面的代码块;是 False,执行 else 下面的代码块。二选一,没有中间地带。

之前那个年龄判断就是典型的 if-else。我再给个稍微实际点的例子——判断一个整数是奇数还是偶数:

num = int(input("请输入一个整数:")) if num % 2 == 0: print(f"{num} 是偶数") else: print(f"{num} 是奇数")

这里用到了取余运算符%。num % 2的意思是 num 除以 2 的余数,如果余数为 0,说明能被 2 整除,那就是偶数。这个场景在真实项目里出现频率极高——不只是判断奇偶,任何需要"按余数分流"的逻辑基本都是这个思路。

if-else 有一个非常隐蔽的坑需要留意:if 和 else 必须保持在同一个缩进级别。因为 else 是和 if 配对的,如果你把 else 的缩进搞乱了,程序要么报错,要么逻辑完全变样——它可能会错误地挂到了别的 if 上。

2.3 elif:多条件分流的"阶梯"

现实中的判断往往不止两种情况。比如给考试成绩分等级:90 分以上是优秀,80 到 89 是良好,60 到 79 是及格,60 以下是不及格。这种多档位的判断,就需要 Python 提供的 elif 语法。

score = int(input("请输入考试成绩:")) if score >= 90: print("优秀") elif score >= 80: print("良好") elif score >= 60: print("及格") else: print("不及格")

这段代码的判读逻辑是从上往下依次判断:先看score >= 90,如果成立直接输出"优秀",后面的 elif 和 else 全部跳过;如果不成立,再看score >= 80……一直到某个条件成立为止,如果所有条件都不成立,最后执行 else。

这里有一个新手非常容易搞错的思想要点:elif 的条件判断是"接力式"的。当程序检查到score >= 80的时候,其实隐含了一个前提——前面的score >= 90已经不成立了,所以这个分数必然小于 90。因此elif score >= 80真正表达的语义是"分数在 80 到 89 之间"。如果你意识不到这一点,将来写条件时容易画蛇添足,比如写成elif score >= 80 and score < 90。这样做虽然逻辑也没错,但不必要——前面的 if 已经帮你筛掉大于等于 90 的情况了。

有些初学者会问:那我用多个独立的 if 行不行?

if score >= 90: print("优秀") if score >= 80: print("良好") if score >= 60: print("及格")

行倒是行,但结果完全不对。用户考了 95 分,会连续输出"优秀""良好""及格"三行。因为每个 if 都是独立判断的,互不干扰。记住一句话:当你需要"多条路只走一条"的时候,用 if-elif-else;当你需要"多个条件独立判断互不影响"的时候,才用多个 if。

3. 循环的两种基本形态:while 和 for

3.1 为什么需要循环:重复劳动交给机器

写程序的人最讨厌的一件事就是重复。比如你想打印 1 到 100 的数字,如果不用循环,你得写 100 行 print 语句。这还只是 100,如果要打印 1 到 10000 呢?写到你怀疑人生。

循环结构就是为了解决"大量重复操作"而生的。它的核心思想是:让一段代码反复执行,直到某个条件不再满足为止。

Python 里有两套循环体系,分别是 while 循环和 for 循环。初学者常见的困惑是不知道该用哪个,其实只要搞清楚两者的适用场景就行。

3.2 while 循环:只要条件成立就一直做

while 循环的结构跟 if 非常相似,区别在于:if 是"条件成立就执行一次",while 是"条件成立就反复执行,每次执行完回头看条件,直到条件不成立为止"。

count = 1 while count <= 5: print(count) count = count + 1

这段代码的执行过程可以拆解为:

  1. 先把count设为 1
  2. 检查count <= 5,结果为 True,进入循环体
  3. 打印count(也就是 1),然后count变成 2
  4. 回到第 2 步,重新检查条件,此时count = 2,依然 True
  5. 继续循环……直到count变成 6,此时count <= 5为 False,循环终止

这个"检查条件-执行循环体-再检查条件"的往复过程,是理解 while 循环的关键。很多人学了很久都搞不清 while 的执行顺序,其实就用四个字记:先判后行。先判断条件,再执行循环体。

3.3 while 循环的死循环陷阱

刚才那个例子,每执行一次循环体,count都会加 1。如果我把count = count + 1这一行去掉,会发生什么?

count = 1 while count <= 5: print(count)

count永远是 1,count <= 5永远为 True,循环永远不会结束。这就是传说中的死循环。程序会一直打印 1,直到你强制终止它。这一步不小心,轻则程序卡死,重则占用大量 CPU 资源。

所以写 while 循环时,一定要反复问自己一个问题:循环体里有没有哪行代码在改变条件涉及的值?如果一个 while 循环的循环体里没有任何改变判断条件的操作,那这个循环十有八九是个死循环。

不过死循环也不全是坏事。有些程序就是故意要一直运行下去的——比如聊天软件的服务器,它需要 7x24 小时不间断地监听新消息。你看到一个程序"卡住不动"但它没有报错,很可能就是故意设计成了死循环。

3.4 for 循环:沿着队列逐个处理

for 循环跟 while 的思维方式不太一样。while 是"只要条件成立就一直做",for 是"沿着一个序列,把里面的元素逐个拿出来处理"。它的语法是:

for 变量 in 序列: 循环体

从序列里拿一个元素赋给变量,执行一次循环体;然后拿下一个元素,再执行一次循环体;直到序列里的元素全被拿完,循环结束。

举个最典型的例子,遍历一个列表:

fruits = ["苹果", "香蕉", "橘子"] for fruit in fruits: print(f"我吃了一个{fruit}")

这个循环的执行过程是这样的:第一次循环,fruit = "苹果",打印"我吃了一个苹果";第二次,fruit = "香蕉",打印"我吃了一个香蕉";第三次,fruit = "橘子",打印"我吃了一个橘子"。序列到头了,循环结束。

注意,for 循环里的那个变量名可以随便起,但最好有意义。比如遍历列表students,变量名就叫student;遍历字符串里的每个字符,变量名就叫char。好的命名让你写出来的代码像句子一样通顺。

3.5 range 函数:生成数字序列的利器

for 循环最常见的搭档就是range()函数。这个函数能生成一个整数序列,在配合 for 做"重复固定次数"的操作时特别好用。

for i in range(5): print("第", i, "次循环")

range(5)生成的是 0、1、2、3、4 这五个数。所以这个循环会执行 5 次,但i的值是从 0 开始的。这个从 0 开始的现象让不少新手疑惑:我想循环 5 次,为什么不从 1 开始?

很简单,因为 Python 的索引体系就是从 0 开始的。列表的第一个元素下标是 0,第二个是 1,以此类推。所以当你用range(5)去遍历一个长度为 5 的列表时:

lst = [10, 20, 30, 40, 50] for i in range(5): print(lst[i])

i是 0 时访问lst[0],也就是第一个元素;i是 4 时访问lst[4],也就是最后一个元素。完美对应。

range()还可以接收两个甚至三个参数:

  • range(1, 6):生成 1 到 5 的序列,注意是左闭右开——包含左边的 1,不包含右边的 6
  • range(1, 10, 2):生成 1、3、5、7、9,第三个参数是步长,也就是每次跳几个数

这个左闭右开的设计让很多人一开始不太适应,但只要你记住一句口诀——"顾头不顾尾",基本就不会错了。range(a, b)生成的序列包含 a 但不包含 b。

4. 分支和循环组合:典型场景实战拆解

4.1 场景一:数字累加器

先来一个入门必练的小项目:计算 1 到 100 的所有整数之和。这个题目看着简单,但第一次接触循环的人很少有能一遍写对的。

total = 0 for i in range(1, 101): total = total + i print("1到100的和是:", total)

我详细拆一下思路。首先,我们需要一个变量total来装累加的结果,初始值是 0。然后range(1, 101)会依次产生 1、2、3……一直到 100。每次循环,total = total + i都把当前的i值累加到总量里。循环结束后,total 就是 5050。

这个"累加器"模式在真实开发中太常用了——统计订单总金额、计算购物车总价、汇总报表数据,全都是这个套路:先初始化一个变量,然后在循环里不断更新它。

4.2 场景二:连续输入的成绩统计

累加器只是单向操作,如果循环里再嵌套分支判断,威力就大不一样了。比如,我们要统计一批成绩里有多少人及格、多少人不及格,还要算出平均分。

total_score = 0 pass_count = 0 n = int(input("请输入学生人数:")) for i in range(n): score = int(input(f"请输入第{i+1}个学生的成绩:")) total_score = total_score + score if score >= 60: pass_count = pass_count + 1 average = total_score / n print("平均分是:", average) print("及格人数:", pass_count)

你可以看到,循环体内嵌了一个 if 判断。用户在循环里每次输入一个成绩,先累加总分,再判断是否及格并计数。这就是循环里套分支的典型结构。

这里有个小细节值得注意:f"请输入第{i+1}个学生的成绩"中的{i+1}是因为用户看到的编号是从 1 开始的,而循环变量 i 是从 0 开始的。这种"人对不上号"的困扰非常常见,养成自觉偏移的习惯能省很多事。

4.3 场景三:猜数字小游戏

如果把前两个场景再升级一下,加进 while 循环,就能写一个交互感很强的猜数字小游戏了。这也是很多人最早感受到编程乐趣的程序之一。

import random target = random.randint(1, 100) guess = -1 while guess != target: guess = int(input("请猜一个1到100之间的数字:")) if guess > target: print("猜大了!") elif guess < target: print("猜小了!") else: print("恭喜!猜中了!")

分析一下这个程序的执行过程。目标数字由random.randint(1, 100)随机生成。guess初始值为 -1,保证一定能进入循环(因为 -1 肯定不等于目标值)。

每次循环,用户输入一个数字,然后根据猜的数字和目标数字的大小关系走不同的分支:大了、小了、中了。猜中时,guess等于target,下次回到 while 条件检查时,条件为 False,循环退出。

这个例子非常巧妙地用到了上一节学的知识:while 的"先判后行"、if-elif-else 的"接力判断"、以及变量在循环中不断被重新赋值的模式。

5. 初学阶段高频踩坑实录:缩进、死循环、边界值

5.1 缩进错了,逻辑全乱

Python 里缩进不只是"为了好看",它就是语法本身。同一个代码块的语句必须有相同的缩进量,而且通常约定用四个空格。

最容易翻车的一种情况是:if 条件本来只想控制一行,结果下面跟着好几行,你忘了哪些行该缩进。比如:

if score >= 60: print("及格") print("恭喜通过考试") print("成绩评估结束")

这里print("恭喜通过考试")和print("及格")缩进相同,都属于 if 的代码块。而print("成绩评估结束")没有缩进,不在 if 里。如果你想让"恭喜通过考试"在不及格时不出现,那这个写法就是对的;如果你想让它在任何情况下都出现,就得把它取消缩进。

这种问题在代码量小的时候一眼就能看出来,但在几百行的代码里,缩进错误会让你排查到怀疑人生。我的建议是:编辑器里打开"显示空格/制表符"的开关,并且全程只用空格,不用 Tab(或者反过来,但千万别混用)。混用 Tab 和空格在 Python 3 里直接会报错,这是规矩。

5.2 死循环 + 缺少用户退出机制

while 循环里还有一个非常典型的"软死循环"问题——就是程序不是在无限跑,而是跑起来停不下来,因为你没给用户提供退出途径。

比如你写一个菜单系统:

while True: choice = input("请输入选项:") if choice == "1": print("执行功能1") elif choice == "0": print("退出成功") break

注意这里的break关键字,它的作用是强制跳出当前循环。这个程序用while True构造了一个"永远为真"的循环,这样才能不断展示菜单让用户选择。而退出靠的是choice == "0"时触发的break。

没有break或者任何其他退出条件,这个菜单就永远出不去了,用户只能强制关闭整个程序。所以,凡是写while True这种无限循环,一定要问自己:循环体里有没有break?出路在哪?

5.3 边界值:循环次数永远比想象的多一次或少一次

边界值问题是我在带新人时最常强调的,也是考试、面试里最爱的出题点。回到range的左闭右开特性:

for i in range(1, 5): print(i)

这个循环输出的是 1、2、3、4,没有 5。很多初学者想当然地以为range(1, 5)包含 1 到 5,结果发现少了一次,最后一位就是取不到。

我建议你在初次接触循环时养成一个习惯:先用手推一遍小规模数据。比如range(1, 5),自己在草稿纸上写下 1、2、3、4,再看程序输出是否一致。这种手动推算不仅能帮你理解执行过程,还能在调试时快速定位逻辑错误。

再给你一个实战中的例子。假设你想让程序打印 5 个星号,写了:

for i in range(5): print("*", end="")

输出结果是五个星号。但如果你写成了range(1, 5),输出的就只有四个星号。这种"差一个"的问题在分数统计、报表生成、批量处理这些场景里通常很隐蔽——因为程序不报错,只有最终结果跟预期对不上时你才会察觉。

5.4 逻辑运算符的短路效应

最后分享一个稍微进阶一点的细节,但在分支判断里非常实用。Python 的逻辑运算符and和or有个特点——短路求值。

什么意思?当程序执行a and b时,如果a已经是 False,那么无论b是什么,整个表达式必然是 False,Python 就不会再去计算b了。同理,a or b中如果a是 True,整个表达式必然是 True,Python 不会去碰b。

这个特性在真实项目里有个经典用法:安全判断。

if user != None and user.is_vip(): print("欢迎VIP用户")

如果user是 None(表示用户不存在),user != None为 False,后面的user.is_vip()根本不会被调用,也就不会因为 user 不存在而报错。你要是把顺序写反了,写成user.is_vip() and user != None,那么当 user 为 None 时,程序会直接抛异常。这个"把安全的判断放前面"的小技巧,关键时刻能帮你少写很多防御代码。

6. 结课练习与下一步打算

这一讲的内容到这里就接近尾声了。按照惯例,留两道题供你自己练手巩固,每一道都涵盖了分支和循环的核心知识点:

练习一:让用户输入一段文本,程序统计这段文本中字母、数字、空格以及其他字符各自的数量。提示:你可以用 for 循环逐个遍历字符,然后用if、elif、else做分类计数。

练习二:让用户猜一个随机生成的 1 到 100 之间的数,但最多只允许猜 6 次。每猜一次,程序提示"大了""小了"或者"猜中了",超过 6 次还没猜中,输出正确答案。提示:需要用到计数器,结合 while 循环和 break 来设计退出条件。

我在实际带新人时发现,很多人学到这个阶段会犯一个共同毛病:急着去网上找代码抄。我的建议恰恰相反——不要看答案,先自己动手写,哪怕写错也比不写强。你现在犯的每一个缩进错误、每一条跑偏的逻辑,都是在为将来排查复杂 bug 累积经验。等你有底气让上面两道题在不出错的情况下跑通,就可以进入下一讲,去学习循环的进阶玩法——嵌套循环、break 和 continue 的配合、以及更灵活的循环控制技巧,那将是另一番天地。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 21:50:36

Python装饰器全解析:原理、进阶与实战经验

装饰器这东西&#xff0c;我第一次接触的时候是在某个同事的代码里看到一个符号摆在一个函数头上&#xff0c;当时第一反应是“这是什么魔法&#xff1f;”。后来自己动手写了一个带参数的装饰器&#xff0c;才恍然大悟——其实它没那么玄乎&#xff0c;就是“函数套函数”的语…

作者头像 李华
网站建设 2026/10/13 21:50:32

最小二乘法系统辨识:MATLAB实现、阶次选择与避坑指南

简介&#xff1a;这份MATLAB程序包面向自动化、控制工程及信号处理方向的学习者与研究人员&#xff0c;用于系统辨识课程的实验与算法验证。包内共7个文件&#xff0c;全部为.m脚本&#xff0c;压缩包约7KB&#xff0c;涵盖普通最小二乘、递归最小二乘、扩展递归最小二乘、广义…

作者头像 李华
网站建设 2026/10/13 21:48:54

CNN卷积层与池化层原理详解:从参数计算到PyTorch实战

1. 卷积层与池化层的核心工作原理解读1.1 卷积层到底在做什么&#xff1a;一个生活视角在正式敲代码之前&#xff0c;我想先和你一起把卷积层这件事彻底想明白。回到系列前几篇&#xff0c;我们已经解决了"怎么用线性层激活函数搭出一个能跑的网络"的问题&#xff0c…

作者头像 李华
网站建设 2026/10/13 21:43:38

基于深度学习的恶意加密流量检测系统设计与实现

简介&#xff1a;基于深度学习的恶意加密流量检测系统毕业设计项目&#xff0c;以Python实现完整源码与配套文档&#xff0c;面向正在筹备毕业设计、课程设计或期末大作业的高校学生&#xff0c;提供一套可直接运行的检测原型。压缩包共217个文件&#xff0c;核心部分包括4个Py…

作者头像 李华
网站建设 2026/10/13 21:42:36

弗洛伊德算法详解:多源最短路径的Java实现与避坑指南

1. 核心思想与适用场景1.1 多源最短路径问题到底在解决什么先说个直白的场景&#xff1a;你手里有一张城市交通图&#xff0c;上面有若干个站点&#xff0c;站点之间有一些直达线路&#xff0c;每条线路有一个耗时。现在你想知道任意两个站点之间、经过中转后最短的耗时分别是多…

作者头像 李华
网站建设 2026/10/13 21:41:13

纯Java构建企业级AI Agent Harness平台:从架构设计到踩坑实战

做企业级 AI Agent 的人&#xff0c;大概都有过这种感觉&#xff1a;模型选型一堆、工具调用一堆、会话状态一团乱麻&#xff0c;最后发现真正难的不是让大模型“开口说话”&#xff0c;而是给这群 Agent 搭一个能稳定、可控、可追溯的“窝”。这个窝&#xff0c;就是 Harness—…

作者头像 李华