一、什么是选择结构
先看三句生活里的话:
- 如果下雨,我就带伞(不下雨就不带);
- 体温超过 38 度,就去医院(没超过就不去);
- 分数 90 以上是 A,80 以上是 B,60 以上是 C,否则不及格。
这三句话有同一个套路:先问一句「是不是」,再决定做哪件事。程序里的选择结构就是把这种套路翻译成代码。
前面几篇里的代码都是「一条道走到黑」——写几行就从上到下执行几行。从这一篇开始,程序会看着办了:条件成立走这条路,不成立走那条路。
Python 的选择结构,常见的长相就下面这几种:
| 类型 | 长相 | 一句话解释 | 本篇第几节 |
|---|---|---|---|
| 单分支 | if 条件: | 条件成立就做,不成立就跳过 | 第三节 |
| 双分支 | if 条件: … else: … | 两条路里挑一条走 | 第四节 |
| 多分支 | if 条件1: … elif 条件2: … else: … | 多条岔路里挑一条走 | 第五、六节 |
| match 分支 | match 值: … case 值1: … case _: … | 拿一个值去和一堆候选值比,命中一个就停 | 第七节 |
另外还有几个「加料」的玩法:match 语句(拿一个值去挑分支,第七节)、嵌套(分支里面再放分支,第八节)和跳转表(用字典代替一大串 elif,第十节)。
and/or/not、什么算真什么算假),在《13-条件表达式》里已经讲透了。这一篇第九节只给一张速查表,不重复展开。二、if 语句的四个零件
单分支的骨架只有两行。下面是「长相」示意图,把 条件 换成真实判断(比如 age >= 18)才能运行:
# 示意:把「条件」换成真实判断,例如 age >= 18
if 条件:
条件成立时要执行的代码
看着简单,但它有四个零件,缺一个都跑不起来:
| 零件 | 例子里的样子 | 要求 |
|---|---|---|
① 关键字 if | if | 全小写,不能写成 If 或 IF |
| ② 条件 | age >= 18 | 一句结果是 True 或 False 的话 |
| ③ 冒号 | : | 必须是英文半角冒号,中文的 : 会报错 |
| ④ 缩进 | 行首 4 个空格 | 告诉 Python「这一行属于上面那个 if」 |
把零件装上,就是一个完整的例子:
age = 20
if age >= 18:
print('您已成年,可以进入!')
运行结果:
您已成年,可以进入!
缩进是「分组」的意思
缩进不是为了让代码好看,而是在划范围:缩进相同的几行,算同一组。
age = 20
if age >= 18:
print('第一句') # 属于 if 这一组
print('第二句') # 也属于 if 这一组
print('这句永远执行') # 缩回去了,已经跑出 if 的范围
运行结果:
第一句
第二句
这句永远执行
if …: 那一行按回车后,编辑器会自动帮你缩进 4 格。想提前结束这一组,按一下退格键(或者 Shift + Tab)让光标退回来就行。缩进统一用 4 个空格,不要一半用 Tab 一半用空格。课程思政|工匠精神与严谨求实 · 半角冒号里的规矩
if 的四个零件里,冒号必须是英文半角,缩进得老老实实四个空格。一个全角冒号、一次少敲空格,程序立刻给你颜色看。这些「琐碎」恰恰是工程素养的底色——代码是要给别人读、给机器跑的,规矩统一了,接手的人才不必替你收拾。先把细节做扎实,再谈什么大项目。
三、单分支:条件成立才做事
单分支是最简单的选择结构:条件成立就做那件事,不成立就跳过,什么都不发生(不会报错,也不会提示)。
案例 1:未成年就限时(游戏防沉迷)
age = 16
if age < 18:
print('未成年人,今日游戏限时 1 小时')
未成年人,今日游戏限时 1 小时
把 age 改成 20 再跑一次,屏幕上什么都没有——因为条件不成立,整个缩进块被跳过了。
案例 2:凑够满减才提示(外卖)
price = 25
if price >= 20:
print('已满 20 元,可以领 5 元券')
已满 20 元,可以领 5 元券
案例 3:购物车是不是空的
空列表在 Python 里算「假」,所以直接写 not cart 就行,不用写 len(cart) == 0。
cart = []
if not cart:
print('购物车还是空的')
购物车还是空的
案例 4:校园卡余额够不够
balance = 8.8
price = 12
if balance >= price:
print('余额充足,可以购买')
校园卡里只剩 8.8 元、一份套餐要 12 元,条件不成立,屏幕上没有输出。这时你可能会盯着屏幕发呆:「怎么没反应?」——没反应就是正常反应。
案例 5:抽到 SSR 才庆祝(盲盒)
card = 'SSR'
if card == 'SSR':
print('恭喜抽到 SSR!')
恭喜抽到 SSR!
四、双分支:二选一
把两条路都写出来,就是双分支(同样是示意,不是能直接跑的真代码):
# 示意:把「条件」和两边的「要做的事」换成自己的内容
if 条件:
条件成立时走这里
else:
条件不成立时走这里
else 那一行后面只跟一个冒号,不能写条件。写 else score < 60: 会直接报错。else 的意思就是「剩下的所有情况」。案例 1:奇数还是偶数
num = 7
if num % 2 == 0:
print(f'{num} 是偶数')
else:
print(f'{num} 是奇数')
7 是奇数
% 是取余数,num % 2 就是「除以 2 剩多少」:剩 0 是偶数,剩 1 是奇数。
案例 2:密码对不对
password = input('请输入密码:')
if password == '123456':
print('登录成功!')
else:
print('密码错误!')
输入 123456 时输出「登录成功!」;输入别的就输出「密码错误!」。
案例 3:地铁进站,余额够不够
balance = 5
if balance >= 3:
print('余额够,进站成功')
else:
print('余额不足,请先充值')
余额够,进站成功
案例 4:外卖满不满减
price = 25
if price >= 20:
print('满 20,减 5 元')
else:
print('还差一点,凑单可减 5 元')
满 20,减 5 元
案例 5:工作日还是周末
day = '星期六'
if day in ['星期六', '星期日']:
print('周末,可以休息')
else:
print('工作日,要上课')
周末,可以休息
案例 6:输入的是不是数字
字符串自带一个方法 isdigit(),专门用来问「这一串是不是全是数字」。
user_input = input('请输入一个内容:')
if user_input.isdigit():
print('你输入的是数字')
else:
print('你输入的不是数字')
level = '及格' if score >= 60 else '不及格'。岔路多于两个时,还是回来用 if / elif / else。课程思政|数据安全与法治素养 · 密码不该躺在代码里
这一节里「密码对不对」的例子,是把口令直接写死在代码里比对的。课堂上没问题,真做系统却是大忌:源代码一旦泄露,所有人的密码就跟着曝光。能拿到,不等于就该这样存。今天先改掉弱口令、养成不硬编码敏感信息的习惯,将来经手用户的账号、成绩、消费记录时,你才守得住别人的信任。
五、多分支:多个岔路
岔路超过两个,就用 elif(它是 else if 的缩写)继续往下接(下面是示意):
# 示意:岔路多了,就一路 elif 接下去
if 条件1:
条件1成立时做的事
elif 条件2:
条件1不成立、条件2成立时做的事
elif 条件3:
前面都不成立、条件3成立时做的事
else:
上面全都不成立时做的事(这一节可以省略)
else if 这种写法,一定要写成一个词 elif。写成 else if 会报语法错误。案例 1:成绩等级 A / B / C / D / F
score = 85
if score >= 90:
print('成绩等级为 A')
elif score >= 80:
print('成绩等级为 B')
elif score >= 70:
print('成绩等级为 C')
elif score >= 60:
print('成绩等级为 D')
else:
print('成绩等级为 F')
成绩等级为 B
85 分从第一条往下一路问下来:90 以上吗?不是;80 以上吗?是——于是打印 B,后面的条件根本不会再问。
案例 2:BMI 分类
bmi = 22.5
if bmi < 18.5:
print('偏瘦')
elif bmi < 24:
print('正常')
elif bmi < 28:
print('偏胖')
else:
print('肥胖')
正常
案例 3:根据月份判断季节
示例里用了连续比较 3 <= month <= 5,这是 Python 特有的写法,意思是「month 大于等于 3 并且小于等于 5」。
month = 3
if 3 <= month <= 5:
print('春季')
elif 6 <= month <= 8:
print('夏季')
elif 9 <= month <= 11:
print('秋季')
else:
print('冬季')
春季
案例 4:数字转星期几
day = 3
if day == 1:
print('星期一')
elif day == 2:
print('星期二')
elif day == 3:
print('星期三')
elif day == 4:
print('星期四')
elif day == 5:
print('星期五')
elif day == 6:
print('星期六')
elif day == 7:
print('星期日')
else:
print('输入的数字不在 1-7 范围内')
星期三
match 语句,或者第十节的跳转表(七个 elif 压成一个字典,读起来清爽得多)。六、elif 的三条铁律
多分支能跑起来不难,难的是写对顺序。这三条一定要记住。
铁律一:从上往下一句句问
程序不是「同时看所有条件」,而是从第一个 if 开始,一句一句往下问。
铁律二:命中一个就停下
只要有一个条件成立,执行完它那一组代码,整个 if / elif 链就结束了,后面的条件连看都不看。
铁律三:顺序不能乱,宽的条件要往下放
看这个写错的例子:
score = 95
if score >= 60:
print('及格')
elif score >= 90:
print('优秀')
及格
95 分明明是优秀,却打印了「及格」!因为 score >= 60 先被问到、又正好成立,程序打印完就掉头走了,永远轮不到 score >= 90。把两条换个位置就对了:
score = 95
if score >= 90:
print('优秀')
elif score >= 60:
print('及格')
优秀
>= 60 这种最宽的条件,放到最后当 else 的前一步,绝不会出错。顺带弄清:两个独立的 if 和 if / elif 有什么区别?
这是新手最容易混淆的一处。两个独立的 if 会各问各的,可能同时命中;if / elif 只会命中一个。
score = 95
print('--- 两个独立的 if ---')
if score >= 90:
print('优秀')
if score >= 60:
print('及格')
print('--- if / elif ---')
if score >= 90:
print('优秀')
elif score >= 60:
print('及格')
--- 两个独立的 if ---
优秀
及格
--- if / elif ---
优秀
同样是 95 分:两个独立 if 打印了两行,if / elif 只打印了一行。用哪个,取决于你的需求——「只挑一条路」用 elif,「每条规则都要独立检查」才用两个 if。
七、match 语句:多分支的新写法
较新的 Python 3 版本里,选择结构还多了一个新成员——match 语句。它长得有点像其他语言里的 switch / case,专门处理一种很常见的多分支:拿一个值,去和一堆候选值挨个比一比,跟谁对得上就走谁。
先看长相。下面是示意图,把「值」和「候选值」换成真实内容才能跑:
# 示意:把「值」换成要判断的变量,把「候选值」换成真实的值
match 值:
case 候选值1:
命中候选值1时要做的事,可以写好几行
case 候选值2:
命中候选值2时要做的事
case _:
前面都没命中时要做的事
三个零件,格式要求和 if 一样严格:
| 零件 | 样子 | 要求 |
|---|---|---|
① match | match 值: | 要判断的那个值,后面跟英文冒号 |
② case | case 候选值: | 一个候选写一行,有几行就有几个候选,后面也要冒号 |
③ case _: | case _: | 兜底:上面全都没命中时走这里,相当于 else |
if 一样,冒号必须是英文半角,case 下面的代码要缩进 4 格,同一个 match 里的所有 case 要对齐。漏冒号、乱缩进,报的错和 if 一模一样。case _: 里的下划线 _ 是「随便什么都行」的意思,作用等于 if 里的 else。建议每个 match 都留一个 case _: 兜底,免得输入了意料之外的值、程序一声不吭。案例 1:数字转星期几
第五节的案例 4 是用七个 elif 写的,这里换成 match 再写一遍,对比着看:
day = 3
match day:
case 1:
print('星期一')
case 2:
print('星期二')
case 3:
print('星期三')
case 4:
print('星期四')
case 5:
print('星期五')
case 6:
print('星期六')
case 7:
print('星期日')
case _:
print('输入的数字不在 1-7 范围内')
星期三
「一个数字对应一个星期几」这种一对一的多分支,用 match 一眼就能看出对应关系,改起来也方便——想加一条规则,直接加一个 case 就行。
案例 2:命令菜单
平时写的小工具经常要认命令,这种「字符串对字符串」的匹配正是 match 的拿手戏:
command = 'quit'
match command:
case 'start':
print('正在启动...')
case 'pause':
print('已暂停')
case 'quit':
print('退出程序')
case _:
print('未知命令,请重新输入')
退出程序
案例 3:case 后面再加一个 if(守卫)
case 后面跟的是一个值,不是一句条件——所以不能直接写 case >= 90:(那是语法错误)。想按范围判断,要在值后面再接一个 if,这个 if 叫守卫:
score = 85
match score:
case s if s >= 90:
print('优秀')
case s if s >= 60:
print('及格')
case _:
print('不及格')
及格
这里的 case s 意思是「先把命中的值收进变量 s」,后面 if s >= 60 再拿 s 去问一句。
case,排序规则和第六节的 elif 铁律一模一样:越「宽」的条件越往下放。要是把 case s if s >= 60: 放到前面,85 分就会被它先拦住,永远轮不到「优秀」。案例 4:一次匹配好几个值(用 |)
| 读作「或者」,能把几个候选并进同一个 case:
answer = 'Y'
match answer:
case 'y' | 'Y':
print('你选择了「是」')
case 'n' | 'N':
print('你选择了「否」')
case _:
print('请输入 y 或 n')
你选择了「是」
case 'y' | 'Y': 相当于 if 里写 answer == 'y' or answer == 'Y',但更短、更整齐。
案例 5:匹配「结构」(进阶,了解即可)
match 比一般的 switch 更强的地方,是它还能比结构——比如「两个数组成的元组」,顺便把每个位置上的数取出来用:
point = (0, 5)
match point:
case (0, 0):
print('原点')
case (0, y):
print(f'在 y 轴上,y = {y}')
case (x, 0):
print(f'在 x 轴上,x = {x}')
case (x, y):
print(f'普通点 ({x}, {y})')
在 y 轴上,y = 5
这一段用到元组和 f-string,如果还没学到,跳过完全没问题,知道「match 还能按结构拆着匹配」就够了。
那到底用 match 还是 if / elif?
| 要判断的情况 | 推荐写法 |
|---|---|
| 一个值 vs 一堆固定候选(都是「等于」) | match,或者第十节的跳转表 |
条件里有大小比较(>=、<、一个范围) | if / elif |
| 几个不同变量一起判断,或者判断真假 | if / elif |
| 要顺便把结构里的值取出来用 | match(案例 5) |
match 是较新的 Python 3 版本 才加入的语法。如果版本太老,运行到 match 那一行会报 SyntaxError: invalid syntax。用 python --version 看一下自己的版本——装官网最新的 Python 3 就完全支持。match 只是多了一种写法,不是 if 的替代品:判「等于某个值」用它清爽;判大小、判真假、几个变量一起判断,还是 if / elif 更直接。基础阶段先把 if 用熟,match 当锦上添花就好。AI 助手小贴士|选择结构的 bug 往往不报错、只是「算错」,让 AI 帮你盯边界和顺序。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:我的成绩等级判断程序 90 分输出了「良好」而不是「优秀」,请帮我检查 if/elif 的条件顺序和边界值问题:<描述或贴代码>
八、嵌套:分支里再放分支
嵌套就是在一个分支里面,再写一整套分支。语法上没有任何新东西,只是缩进多一层(每进一层加 4 个空格)。
案例 1:先看下不下雨,再看带没带伞
raining = True
has_umbrella = False
if raining:
if has_umbrella:
print('下雨,但带了伞,不慌')
else:
print('下雨又没带伞,快跑')
else:
if has_umbrella:
print('没下雨,伞白带了')
else:
print('没下雨,轻松出门')
下雨又没带伞,快跑
读代码的窍门:先看缩进最浅的那一层。这里最外层只有一个 if / else(分下没下雨),每个分支里又各自藏了一套小 if / else(分带没带伞)。
案例 2:某年某月有几天
这个例子很实用:先看月份是 31 天还是 30 天,2 月再单独看是不是闰年。
year = 2026
month = 2
if month in [1, 3, 5, 7, 8, 10, 12]:
print(f'{year} 年 {month} 月有 31 天')
elif month in [4, 6, 9, 11]:
print(f'{year} 年 {month} 月有 30 天')
elif month == 2:
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
print(f'{year} 年 {month} 月有 29 天')
else:
print(f'{year} 年 {month} 月有 28 天')
else:
print('输入的月份不正确')
2026 年 2 月有 28 天
闰年的判断规则:能被 4 整除、且不能被 100 整除;或者能被 400 整除。2024 是闰年,1900 不是(能被 100 整除但除不尽 400),2000 是。
补充:用标准库 calendar.isleap() 一行判断闰年
刚才案例 2 里那一长串 (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) 是「原理」,必须会写;但真做东西时不用自己算——标准库 calendar 有个现成的 calendar.isleap(),交给它年份,它直接告诉你是不是闰年。
import calendar
year = 2026
if calendar.isleap(year):
print(f'{year} 年是闰年,2 月有 29 天')
else:
print(f'{year} 年不是闰年,2 月有 28 天')
2026 年不是闰年,2 月有 28 天
把案例 2 里的内层判断换成 calendar.isleap(year),结果一模一样,代码却短了一半,别人一眼就看懂。自己先用运算符把规则写出来,是为了知道它在干什么;之后直接用标准库,是为了少出错。
案例 3:年龄 + 性别给出不同提示
age = int(input('请输入你的年龄:'))
gender = input('请输入你的性别(男/女):')
if age < 18:
if gender == '男':
print('你是未成年男性')
elif gender == '女':
print('你是未成年女性')
else:
print('输入的性别不正确')
else:
if gender == '男':
print('你是成年男性')
elif gender == '女':
print('你是成年女性')
else:
print('输入的性别不正确')
输入 20 和 男,输出「你是成年男性」。这段代码看着长,其实结构很整齐:外面分成「未成年」和「成年」两半,每一半里面又重复了同一套「男 / 女 / 其他」。
小心:else 跟的是「离它最近的那个同层 if」
x = 5
if x > 0:
if x > 10:
print('大于 10')
else:
print('非正数')
这个 else 和 if x > 0: 缩进一样,所以它配对的是外层那个 if,意思是「x 不是正数时」。x = 5 时外层成立、内层不成立,没有任何输出。
如果你本来想让它是「0 < x ≤ 10 时」的分支,就得把 else 往右缩进一层:
x = 5
if x > 0:
if x > 10:
print('大于 10')
else:
print('0 < x <= 10')
0 < x <= 10
九、条件里能写什么
这一节只做「速查」。详细讲解在《7-运算符》和《13-条件表达式》里。
| 条件写法 | 例子 | 什么时候用 |
|---|---|---|
| 比较 | age >= 18、name == '小明'、n != 0 | 最常用,问「谁大谁小、是否相等」 |
| 逻辑组合 | age >= 18 and score >= 60、a == 1 or b == 2 | 两个条件要同时满足 / 满足一个就行 |
| 取反 | not my_list、not is_full | 问「是不是不……」 |
| 成员判断 | month in [1, 3, 5]、'a' in 'cat' | 问「在不在这一堆里」 |
| 真值判断 | if my_list:、if name: | 问「是不是空的」——空就是假 |
| 直接放布尔变量 | if is_vip: | 这个变量本身就是 True / False |
几个容易写错的点:
age = 20
is_member = True
# 混用 and / or 时,用括号把意思圈清楚
if (age >= 18 and age < 60) or is_member:
print('可以办理')
my_list = []
if not my_list:
print('写法一:空列表')
if len(my_list) == 0:
print('写法二:空列表')
两种写法都对,但第一种更 Python,代码也更短。
name = ''
if name:
print(f'你好,{name}')
else:
print('名字是空的')
名字是空的
空字符串、空列表、0、None 全都是「假」,所以判断「有没有内容」直接写变量名就行。
==,不要用 is。is 问的是「是不是同一个东西」(内存地址),只在判断 None 时才推荐用:if result is None:。十、跳转表:岔路特别多时用字典
如果多分支长成这样——每个条件都是「某个值等于某个数 / 某某字符串」,一写就是七八个 elif——那它其实可以换一种更清爽的写法:把「值 → 结果」做成一张字典表,直接查表。这张表就叫跳转表。
| 写法 | 长得像 | 适合的场景 |
|---|---|---|
| if / elif 链 | 一连串 elif day == 1: … elif day == 2: … | 条件里有大小比较(>=、<、范围) |
| 跳转表 | codes = {'red': '#FF0000', …} 然后 codes[name] | 条件都是「等于某个值」,一对一查表 |
案例 1:颜色名称查颜色代码
color_codes = {
'red': '#FF0000',
'green': '#00FF00',
'blue': '#0000FF',
}
color_name = input('请输入颜色名称(red, green, blue):')
if color_name in color_codes:
print(f'{color_name} 的颜色代码是 {color_codes[color_name]}')
else:
print('未知颜色名称')
先问一句 color_name in color_codes(表里有没有这个键),再放心取值。这是最稳妥的写法。
案例 2:错误码翻译
字典还有一个 get() 方法,可以顺便写好「查不到时用什么」:
error_codes = {
404: '页面未找到',
500: '服务器错误',
200: '成功',
}
print(error_codes.get(404, '未知错误'))
print(error_codes.get(999, '未知错误'))
页面未找到
未知错误
get(键, 默认值):键在表里就把对应的值给你,不在就给你写的默认值,绝不会因为查不到而报错。
案例 3:命令分发(值对应到函数)
字典里不仅可以存字符串,还能存函数。这是跳转表最经典的用法:
def command_help():
print('这是帮助信息')
def command_exit():
print('退出程序')
commands = {'help': command_help, 'exit': command_exit}
action = 'help'
commands.get(action, lambda: print('未知命令'))()
这是帮助信息
课程思政|科技自立自强 · 会查表,才不被分支困住
当每个岔路都是「等于某个值」,硬堆七八个 elif 就不如改用一张字典跳转表,查一下就出结果。同一件事,换更合适的工具,效率立刻不一样。写程序如此,做研究、做工具也一样——把「自己造轮子」的本事一点点练出来,遇到问题时手里的选项才不止一个,这正是技术自立的底气。
十一、最容易搞混的几组
1. = 和 ==
= 是赋值(把右边的值装进左边的变量),== 是比较(问两边相等吗)。条件里写 = 一定报错。
score = 85 # 对:把 85 存进 score
if score == 85: # 对:问 score 是不是 85
print('满分')
写成 if score = 85: 会报 SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?——好消息是 Python 直接把正确写法提示给你了。
2. else 和 elif
| 写法 | 后面要不要跟条件 | 意思 |
|---|---|---|
elif 条件: | 要 | 前面都不成立,且这个条件成立时 |
else: | 不要 | 前面全都不成立时(兜底) |
3. 两个独立的 if vs if / elif
见第六节的实测例子:95 分时,两个独立 if 会打印两行,if / elif 只打印一行。要「只走一条路」就用 elif。
4. is 和 ==
result = None
if result is None: # 对:判断「没有结果」
print('没有结果')
name = '小明'
if name == '小明': # 对:比较内容一律用 ==
print('找到了')
5. 缩进的 0 个空格和 4 个空格
同一行代码,缩进不同,意思完全不同:
score = 50
if score >= 60:
print('及格') # 缩进了 → 只有及格才打印
print('成绩已录入') # 没缩进 → 永远打印
成绩已录入
6. 条件表达式 vs if 语句
两者都能做二选一,但一个产出值、一个是语句:
score = 72
# 写法一:if 语句——走一条路,做一件事
if score >= 60:
level = '及格'
else:
level = '不及格'
print(level)
# 写法二:条件表达式——一行直接算出值
level2 = '及格' if score >= 60 else '不及格'
print(level2)
及格
及格
if / elif / else。十二、六个综合小练习
下面六个小程序,每个都只有几行,建议先自己猜输出,再敲进去跑一遍。它们都是生活里真会遇到的判断。
练习 1:快递费怎么算
规则:首重 1 公斤以内 12 元,超过 1 公斤的部分每公斤加 8 元。
weight = 2
if weight <= 1:
fee = 12
else:
fee = 12 + (weight - 1) * 8
print(f'重量 {weight} 公斤,快递费 {fee} 元')
重量 2 公斤,快递费 20 元
练习 2:景区门票按年龄定价
6 岁以下免票,6~17 岁 30 元,18~59 岁 60 元,60 岁及以上免票。
age = 25
if age < 6:
price = 0
elif age < 18:
price = 30
elif age < 60:
price = 60
else:
price = 0
print(f'{age} 岁,门票 {price} 元')
25 岁,门票 60 元
把 age 改成 4,输出就是「4 岁,门票 0 元」。
练习 3:石头剪刀布的胜负判定
player = '石头'
computer = '剪刀'
if player == computer:
print('平局')
elif ((player == '石头' and computer == '剪刀')
or (player == '剪刀' and computer == '布')
or (player == '布' and computer == '石头')):
print('你赢了')
else:
print('电脑赢了')
你赢了
注意长条件用括号括起来换行写,比挤成一行好读得多。改 computer = '布' 再跑,就变成「电脑赢了」。
练习 4:三条边能不能组成三角形
规则:任意两边之和都要大于第三边。
a, b, c = 3, 4, 5
if a + b > c and a + c > b and b + c > a:
print('这三条边能组成三角形')
else:
print('这三条边不能组成三角形')
这三条边能组成三角形
把边长改成 1, 2, 5,因为 1 + 2 不大于 5,输出就会变成「不能组成三角形」。
练习 5:体温判断
temp = 38.5
if temp < 37.3:
print('体温正常')
elif temp <= 38:
print('低烧,注意休息')
else:
print('高烧,请及时就医')
高烧,请及时就医
练习 6:停车费分档计算
规则:1 小时以内 5 元;超过 1 小时的部分每小时 3 元;超过 4 小时的部分每小时 5 元。
hours = 3
if hours <= 1:
fee = 5
elif hours <= 4:
fee = 5 + (hours - 1) * 3
else:
fee = 5 + 3 * 3 + (hours - 4) * 5
print(f'停车 {hours} 小时,收费 {fee} 元')
停车 3 小时,收费 11 元
input(),让程序能跟人对话——记得用 int() 或 float() 把输入转成数字,否则会报第十三节里的那个 TypeError。AI 助手小贴士|综合小练习做完想加餐,让 AI 继续出题。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:再给我出 3 道多分支选择题(比如 BMI 分档、出租车分段计费),从易到难,等我提交代码再点评
十三、常见问题(报错手册)
选择结构的报错,八成集中在冒号和缩进上。下面这些都是把错误代码真跑一遍、照抄下来的报错原文。
一、SyntaxError:漏了冒号
age = 20
if age >= 18
print('成年')
SyntaxError: expected ':'
现象:报错行指向 if 那一行。处理:在条件后面补上英文冒号 :。
二、IndentationError:该缩进没缩进
age = 20
if age >= 18:
print('成年')
IndentationError: expected an indented block after 'if' statement on line 2
处理:把 print 那行向右缩进 4 个空格。
三、IndentationError:多缩进了
age = 20
print('你好')
IndentationError: unexpected indent
现象:行首莫名其妙多了空格,它上面却没有 if / for 之类的语句。处理:退格删掉多余缩进,让这行顶格。
四、IndentationError:退回来的位置对不上
age = 20
if age >= 18:
print('成年')
print('第二句')
IndentationError: unindent does not match any outer indentation level
现象:这行缩进了 2 格,但外面只有「0 格」和「4 格」两种层级,对不上号。处理:把缩进改成 4 格(跟上一行同级),或者退回到顶格。
五、TabError:Tab 和空格混着用
if True:
print('a') # 这行的缩进是按 Tab 键产生的
print('b') # 这行的缩进是按 8 次空格键产生的
TabError: inconsistent use of tabs and spaces in indentation
现象:肉眼看两行好像对齐了,Python 却报错。处理:全选代码,统一缩进风格。建议从一开始就只用 4 个空格,IDLE 和 TRAE 默认也是这么做的。
六、SyntaxError:写了 else if
score = 85
if score >= 90:
print('A')
else if score >= 80:
print('B')
SyntaxError: expected ':'
现象:报错行指向 else if 那一行。处理:Python 里要用一个词 elif,中间没有空格。
七、SyntaxError:条件里写了单等号
score = 85
if score = 90:
print('满分')
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
处理:把 = 改成 ==。
八、SyntaxError:用了中文冒号
score = 85
if score >= 60:
print('及格')
SyntaxError: invalid character ':' (U+FF1A)
现象:报错里会出现一个 U+FF1A,那就是中文全角冒号的编号。处理:删掉换成英文冒号。中文输入法下输标点前按一下 Shift 切到英文最省事。
九、SyntaxError:用了中文括号
score = 85
if(score >= 60):
print('及格')
SyntaxError: invalid character '(' (U+FF08)
处理:把 () 换成英文的 ()。凡是报错里出现 invalid character 加上 U+ 开头的编号,基本都是中英文标点混用。
十、SyntaxError:elif 前面没有 if
score = 85
elif score >= 60:
print('及格')
SyntaxError: invalid syntax
现象:elif 只能跟在 if(或别的 elif)后面。else 也是同理,单独出现会报 SyntaxError: invalid syntax。处理:把这个 elif 改成 if,或者补上开头的 if。
十一、SyntaxError:else 后面跟了条件
score = 85
if score >= 60:
print('及格')
else score < 60:
print('不及格')
SyntaxError: expected ':'
处理:else 后面只留一个冒号。如果确实要写条件,那应该用 elif。
十二、SyntaxError:一行里既写 if 又写 else
score = 85
if score >= 60: print('及格') else: print('不及格')
SyntaxError: invalid syntax
注意:if score >= 60: print('及格') 单独一行是合法的(只写条件成立那半边)。但不能在同一条线上再跟 else。想一行搞定,就用条件表达式 '及格' if score >= 60 else '不及格'。
十三、NameError:变量没定义
if score >= 60:
print('及格')
NameError: name 'score' is not defined
处理:条件里用到的变量,必须在这行之前先赋过值。
十四、TypeError:字符串和数字比大小
age = input('请输入年龄:')
if age >= 18:
print('成年')
TypeError: '>=' not supported between instances of 'str' and 'int'
现象:输入数字后照样报错。因为 input() 拿到的永远是字符串,字符串不能和数字比大小。处理:外面套一层转换——age = int(input('请输入年龄:'))。
十五、不算报错,但会让你困惑的几件事
| 现象 | 原因 |
|---|---|
| 条件不成立,屏幕上什么都没有 | 这是正常的,整个缩进块被跳过了。想要提示就补一个 else。 |
某个 elif 里的代码永远不执行 | 大概率是顺序错了:上面有个更宽的条件先命中了(见第六节)。 |
两个 if 各打印了一行 | 它们是两个互相独立的判断,各问各的。想只走一条路要用 elif。 |
| 缩进看着对齐了,还是报错 | 因为 Tab 和空格在屏幕上长得一样、在 Python 眼里不一样。统一用 4 个空格。 |
if 后面暂时不想写代码 | 用 pass 占位:if score >= 60: 下一行缩进写 pass。空着不写会报 IndentationError。 |
想用 switch / case | Python 没有 switch / case 这个关键字。要么用 if / elif,要么用第十节的跳转表;较新的 Python 3 版本 也可以用第七节的 match 语句——它只是多一种写法,基础阶段先把 if 用熟。 |
AI 助手小贴士|选择结构最怕「不报错但判断错」。让 AI 当逻辑审查员,专查走不到的分支和顺序问题。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:我的程序不报错但判断结果不对。请帮我找出 if/elif 逻辑里的漏洞:哪个条件永远走不到、哪个分支顺序该调整?<粘贴代码和错误的运行结果>
十四、随堂自测(12 题)
点击选项即可判分,选错的题会立刻展开解析。做完可以看到正确率和错题清单,也可以重新答题。
1下面哪一行是完整正确的单分支 if 语句开头?
- A.
if age >= 18 - B.
if age >= 18: - C.
if age >= 18; - D.
if (age >= 18)
SyntaxError: expected ':';C 用分号也不对;D 有括号但同样缺冒号。2else 那一行后面应该跟什么?
- A. 一个条件,比如
else score < 60: - B. 什么都不用写,连冒号也不要
- C. 跟
elif - D. 只跟一个冒号
else:
else 表示「剩下所有情况」,后面只跟冒号。写成 else score < 60: 会报 SyntaxError: expected ':';要写条件应该改用 elif。3执行下面这段代码,屏幕上会输出什么?score = 95if score >= 60: print('及格')elif score >= 90: print('优秀')
- A. 只输出「及格」
- B. 只输出「优秀」
- C. 两行都输出
- D. 什么都不输出
score >= 60 先被问到且成立,打印完「及格」整个链条就结束了,elif 永远轮不到。把两条条件交换位置才会输出「优秀」。4Python 里「else if」应该写成什么?
- A.
else if - B.
elseif - C.
elif - D.
else: if
elif,中间不能有空格。写成 else if 会报 SyntaxError: expected ':'。5下面哪种情况会让 Python 报 IndentationError?
- A. 一段代码里混用了 Tab 和空格
- B.
if下面的代码没有缩进 - C. 条件后面漏了冒号
- D. 把
==写成了=
IndentationError: expected an indented block。A 报的是 TabError;C 报 SyntaxError: expected ':';D 报 SyntaxError: Maybe you meant '==' or ':=' instead of '='?。6用 input() 拿到年龄后直接写 if age >= 18:,输入 20 照样报错。为什么?
- A.
input()拿到的永远是字符串,字符串不能和数字比大小 - B. 18 要写成 18.0 才能比
- C. 必须先用
print()打印一次 age - D. 必须写成
if 18 <= age:的顺序
TypeError: '>=' not supported between instances of 'str' and 'int'。处理办法是套一层转换:age = int(input('请输入年龄:'))。7两个独立的 if 和 if / elif 最大的区别是什么?
- A. 独立的
if执行得更快 - B.
if / elif不能写条件 - C. 完全没有区别
- D. 独立的
if可能同时命中多个,if / elif只会命中一个
if 会打印「优秀」和「及格」两行;换成 elif 就只打印「优秀」——因为命中一个后整条链就结束了。要「只走一条路」就得用 elif。8下面这段嵌套代码(else 与外层 if 缩进相同)会输出什么?x = 5if x > 0: if x > 10: print('大于 10')else: print('非正数')
- A. 输出「大于 10」
- B. 输出「非正数」
- C. 什么都不输出
- D. 报错
else 和 if x > 0: 缩进相同,配对的是外层 if,意思是「x 不是正数时」。x = 5 时外层成立、内层不成立,所以什么都不打印。想输出「0 < x ≤ 10」要把 else 再往右缩进 4 格。9判断「列表是不是空的」,下面哪种写法最符合 Python 习惯?
- A.
if len(my_list) == 0: - B.
if not my_list: - C.
if my_list == []: - D.
if my_list is 0:
if not my_list: 最简洁。A 和 C 结果也对,但更啰嗦;D 的 is 判断的是「是不是同一个对象」,这里完全不适用(比较内容一律用 ==)。10「输入颜色名称、输出颜色代码」这类一个值对应一个结果的多分支,本篇推荐用什么写法?
- A. 一直写
elif,写十几个也没关系 - B. 用
while循环一个个试 - C. 用字典做成跳转表,查不到时用
get()给默认值 - D. 用
try / except包起来
color_codes[名字] 直接查表,get(键, 默认值) 还能顺手处理查不到的情况。只有带大小比较(>=、范围)的条件才必须用 if / elif。11关于 match 语句,下面说法正确的是?
- A. 它是较新的
Python 3版本 才加入的;从上往下一路比,命中一个case就结束 - B.
case后面可以直接写>= 90这样的比较 - C. 有了
match之后就不能再用if / elif了 - D.
match里的case一行都不能少,必须把每种情况都写全
match 是较新的 Python 3 版本 新增的语法,脾气和 elif 一样:从上往下一路比、命中一条就停。B 错在 case 后面写的是值不是条件,写 case >= 90: 会报 SyntaxError,要按范围判断得用守卫 case s if s >= 90:;C 错在两者是并列关系,判大小照样用 if / elif;D 错在不需要写全,没匹配到的值直接跳过(想要兜底就补一个 case _:)。12match 语句里,想表示「上面所有 case 都没命中时走这里」,应该怎么写?
- A.
default: - B.
else: - C.
case '': - D.
case _:
match 用 case _: 兜底,下划线 _ 表示「随便什么都行」,作用相当于 if 里的 else。A 的 default: 和 B 的 else: 都不是 match 的语法,会报 SyntaxError;C 只会匹配「空字符串」这一个具体的值,接不住其他情况。