ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python分支结构详解:if/elif/else语法、易错点与经典练习题

Python分支结构详解:if/elif/else语法、易错点与经典练习题 不会吧不会吧还有人觉得Python的分支结构就是“if、else写一写程序就能跑”作为过来人我得说句公道话——真上手写两道题你会发现坑全在细节里。分支结构是Python入门绕不开的第一道坎也是第一个能让你写出“有智能感”代码的知识点。没有它程序只能从头到尾一条线执行有了它程序才敢根据条件走不同的路。这一篇咱们就好好掰扯掰扯分支结构用习题、代码和踩坑记录把这块硬骨头啃干净。这篇东西适合谁看刚把print()和for循环混个脸熟、正准备往逻辑判断上迈步的Python新手以及在if嵌套里绕晕了、想回头补基础的人。咱们的目标是“学完就能写出带判断逻辑的小程序”不整那些花里胡哨的高深理论全是大白话。1. 先搞懂分支结构到底解决了什么问题1.1 没有分支结构程序就是一个死脑筋你想象一下你要写一个自动售票机程序输入年龄然后根据年龄决定票价。三岁的小孩可能免票六十岁的老人可能半价普通成年人全价。如果程序只会从上到下一条路走到黑那它就只能对所有人说“请付全票”。这样的程序放在现实里根本没法用。分支结构就是给程序装上“眼睛”和“脑子”——让它能看看当前的数据长什么样然后决定下一步做什么。Python里面最基础的实现方式就是if / elif / else这套组合拳。它的核心逻辑听起来特别简单如果这个条件成立就执行这一段代码否则的话就执行另一段代码。但就是这么个朴素的东西撑起了登录验证、权限控制、数据清洗、异常分支处理等无数真实业务场景。1.2 分支结构的“三兄弟”各司其职我把if、elif、else称为条件判断中的三兄弟它们的配合方式其实很像我们平时做决定的过程。if是老大负责最核心的那个判断。它后面跟着一个条件表达式后面别忘了加冒号。程序先看看这个条件是真还是假如果是真True就执行它管辖的代码块。elif是老二全称是else if的缩写。它的意思是“前面的if条件不满足那我再来试试我这个条件”。它要放在if的后面可以有很多个程序会从上到下依次去试试到哪个条件满足了就执行哪段代码后面的哪怕条件也满足也不再看了。else是老幺负责兜底。它不需要带条件翻译过来就是“前面说的都不对的话就走我这”。它放在最后面是最后一道防线保证不管出现什么意外情况程序都有路可走。这三兄弟有一个重要特性同一组判断中最多只执行其中一个分支。程序从上往下找找到一个满足条件的就执行然后收工后面的条件不会再检查。这一点很多人刚开始学的时候特别容易忽略以为检查和if条件是互不干扰的结果写出了逻辑漏洞百出的代码。2. 分支结构的语法细节和易错点新手必看2.1 条件表达式里布尔值是怎么来的要理解分支结构先得理解条件判断依赖的布尔值True和False。Python里很多写法都可以直接当作条件来用不一定非要写a b这种比较运算。比如整数0、空字符串、空列表[]、空字典{}、None这些在布尔上下文里都被视为False。而其他非零数字、非空字符串、非空列表、非空字典都被视为True。这是一个非常Pythonic的写法习惯用好了能省好多代码。举几个最常见的条件写法# 判断一个数字是否为0 num 0 if num: print(这个数字不是0) else: print(这个数字是0) # 判断字符串是否为空 name if name: print(fname的值是{name}) else: print(name是空字符串) # 判断列表是否为空 data [] if data: print(列表不是空的) else: print(列表是空的)上面这个写法本质上就是利用了“隐式布尔转换”。但有一点要记住写出来的代码是要给别人看的也是给未来三个月后的自己看的。如果你的条件语义比较绕就不要炫技老老实实写if num ! 0:、if len(data) 0:反而更稳。简洁和清晰之间的平衡是每个程序员要拿捏一辈子的事。2.2 冒号和缩进Python对“格式”的执念Python和C、Java这类用花括号括代码块的语言不一样它用缩进来表示代码块的归属。同一个缩进层级视为同一个代码块缩进层级变化就表示进入了或退出了某个分支。这里有个惨痛教训我在很多初学者作业里见过if条件后面忘了写冒号直接SyntaxError或者缩进混乱有时用两个空格有时用四个空格程序一会儿跑一会儿报错。规范做法是统一用四个空格缩进并且千万不要混用tab和空格。编辑器里的表现是这样的大家感受一下age 20 if age 18: # 这里缩进四个空格属于if管辖的代码块 print(成年人) else: # 这里缩进四个空格属于else管辖的代码块 print(未成年人) # 这里没有缩进属于正常的主流程代码 print(判断结束)如果print(成年人)和if age 18:对齐了那它就跳出了if的作用域无论条件是否成立它都会执行。这种错误跑起来不会报错结果却完全不对特别坑人。2.3 比较运算符里的“双等于”与“单等于”这个坑几乎每个新手都踩过。是赋值它的意思是“把右边的值给左边的变量”是比较它的意思是“看看两个值是否相等相等返回True不然返回False”。# 这样写是赋值不是判断 if score 100: # 语法错误或者变成死循环的逻辑 # 这样写才是判断 if score 100: print(满分)有些语言比如C语言和JavaScript里把写在if条件里可能会触发隐式类型转换或者产生其他奇怪行为但Python在这方面反而“保护”了你——它直接给你一个语法错误让你写不出这种坑人的代码。但新手如果照抄别的语言的写法还是会一头雾水。记住要比较就写两个等号。3. 分支结构核心语法与实操案例拆解3.1 基础形态一单分支——if单分支的形态最简单它只说“如果条件成立我就做这件事条件不成立什么都不做继续往下走”。age int(input(请输入你的年龄)) if age 60: print(老年优惠票价减半) print(购票流程继续)这个代码段里只有age 60成立时才会打印“老年优惠”。如果年龄是30程序就直接跳到print(购票流程继续)执行。注意input()返回的是字符串所以用int()做了转换这个细节在后面会反复出现。3.2 基础形态二双分支——if...else双分支多了一个else它保证了“条件不满足时执行另一段代码”程序不再是“可能什么都不做”而是两条路必走一条。number int(input(请输入一个整数)) if number % 2 0: print(f{number} 是偶数) else: print(f{number} 是奇数)这里%是取余运算符number % 2得到的是number除以2的余数。余数为0说明能被2整除是偶数余数为1是奇数。这个经典判断在面试题里出现的频率极高属于入门必会。3.3 基础形态三多分支——if...elif...else多分支的场景就是用多个条件依次筛选。比如说成绩等级评定90分以上是A80到89是B70到79是C60到69是D60分以下是E。这种“多档位”的判断就是elif的用武之地。score int(input(请输入成绩)) if score 90: grade A elif score 80: grade B elif score 70: grade C elif score 60: grade D else: grade E print(f成绩等级为{grade})这个代码看起来简洁但它能正确工作依赖一个前提条件是从上到下依次判断且只执行第一个满足条件的分支。比如成绩是85score 90不满足进入elif score 80满足执行赋值grade B然后整个判断结束后面的elif score 70都不再检查。所以85分拿到B而不是又匹配了C。如果把条件顺序反过来写从低分到高分score int(input(请输入成绩)) if score 60: grade D elif score 70: grade C elif score 80: grade B elif score 90: grade A else: grade E这样写会出大问题。任何大于等于60分的分数都会在第一个条件就通过直接拿D。学生的85分就只能拿到D逻辑全崩。所以多分支判断一定要注意条件的“筛选顺序”这也是一个非常经典的逻辑错误来源。3.4 嵌套分支if里面再套if有时候一个条件判断还不够要在满足大条件的前提下继续判断小条件。这种“大前提套小前提”的结构就是嵌套分支。age int(input(请输入年龄)) has_ticket input(是否有票(y/n)) if age 18: if has_ticket y: print(可以进场看比赛) else: print(先去买票) else: print(未成年人不能观看该比赛)嵌套分支本身不难理解但嵌套层级一多代码缩进就会越来越深读起来非常累。业界有一个“三层以上嵌套就说明逻辑需要重构”的说法因为嵌套太深后期维护的人真的会崩溃。更好的写法是提前把可以返回的情况先返回或者用and、or把条件合并起来。比如上面这个例子其实可以改写成age int(input(请输入年龄)) has_ticket input(是否有票(y/n)) if age 18 and has_ticket y: print(可以进场看比赛) elif age 18: print(先去买票) else: print(未成年人不能观看该比赛)这种写法逻辑更平铺直叙阅读起来更舒服。但也不是说嵌套一定不好当条件之间有明显的层级关系时嵌套表达反而更自然。这个取舍需要根据具体场景来判断没有一个放之四海而皆准的标准。3.5 三元表达式单行搞定简单双分支Python里还有一种简洁到犯规的写法三元表达式也叫条件表达式。它适合那种“根据条件给变量赋值”的简单场景。# 常规写法 age 20 if age 18: status 成年人 else: status 未成年人 # 三元表达式写法 status 成年人 if age 18 else 未成年人三元表达式的语法结构是值1 if 条件 else 值2。条件为真取值1条件为假取值2。它能在一行内完成简单的判断赋值非常适合在列表推导式、lambda表达式或者简单的返回值里使用。但要注意三元表达式一旦超过一行长度或者嵌套多层可读性就会急转直下# 这种写法虽然能跑但肉眼已经不太好读了 category 儿童 if age 12 else (青年 if age 30 else 中老年)这种嵌套三元表达式我强烈不建议用在正式代码里。自己写着爽别人看着疯。简单的三元表达式是锦上添花复杂的判断还是老老实实用if结构吧。3.6 条件里的逻辑运算and、or、not分支结构往往不是单独一个条件就能搞定的经常需要同时满足多个条件或者满足多个条件中的任意一个。这时候就要用到逻辑运算符and、or、not。and表示“并且”所有条件都为真时结果才为真。比如“年龄大于等于18岁”并且“有票”才能进场。or表示“或者”只要有一个条件为真结果就是真。比如“是会员”或者“消费满500元”都可以享受折扣。not表示“取反”把真变成假把假变成真。比如“不是周末”也想去图书馆那not is_weekend。数学表达上需要注意一个坑初学者经常想把“x在区间[a, b]内”写成a x b这在数学里没问题Python也直接支持这种链式比较会翻译成a x and x b。但如果不清楚这个机制有人会写a x and b x虽然也对但链式写法更直观。score int(input(请输入成绩)) # 经典区间判断 if 60 score 100: print(成绩及格) elif 0 score 60: print(成绩不及格) else: print(成绩超出合理范围请检查输入)另外一个非常隐蔽的坑来自or的短路运算。Python在计算A or B的时候如果A已经为真它就不会再计算B了计算A and B的时候如果A为假也不会再计算B。这个特性叫“短路求值”。平时写代码感觉不到它的存在但如果你在or的右边写了可能报错的代码就能体会到这是保护还是坑了。# 假设x可能为空字符串 x result x or 默认值 print(result) # 输出默认值 # 实际开发中常用这种写法做默认值兜底 name input(请输入名字) or 匿名用户 print(name)or在某种场景下就是一种“兜底”如果前面的值等价于False就使用后面的默认值。这个技巧在配置读取、网络请求返回值处理中非常常见。但需要注意它是基于“隐式布尔转换”的如果条件本身判断的不是“是否为空”而是“是否为特定值”那就不能这么写。4. 用三道经典习题把分支结构焊死在大脑里4.1 习题一闰年判断判断闰年的规则是能被4整除但不能被100整除的年份是闰年或者能被400整除的年份也是闰年。用数学表达就是(year % 4 0 and year % 100 ! 0) or (year % 400 0)。先看最直接的第一版year int(input(请输入年份)) if (year % 4 0 and year % 100 ! 0) or (year % 400 0): print(f{year} 是闰年) else: print(f{year} 不是闰年)这个写法把规则完整翻译成了代码逻辑是对的可读性也还行。但如果想多练练分支结构可以用嵌套的方式再写一遍year int(input(请输入年份)) if year % 4 0: if year % 100 0: if year % 400 0: print(f{year} 是闰年) else: print(f{year} 不是闰年) else: print(f{year} 是闰年) else: print(f{year} 不是闰年)这段嵌套代码逻辑完全正确但缩进已经到5层读起来明显比第一版费劲。对比两个版本就能深刻体会到“逻辑运算合并条件”为什么是更好的实践。判断规则里的“或者”“并且”一旦混在一起用and和or直接表达往往比用嵌套更容易理清思路。再扩展一下有些地区还会把年份小于公元1年的情况考虑进去或者要求判断一个年份区间内所有闰年。区间判断就需要结合循环来做那就是另一个知识点了这里不展开。4.2 习题二分段计费的水费计算先想个现实场景某城市水费采用阶梯计费每月用水量在10吨以内含10吨每吨3元超过10吨但不超过30吨的部分每吨5元超过30吨的部分每吨8元。输入用水量计算总水费。这个问题比闰年判断有挑战性因为要按“区间”分段处理而且每个区间的单价不一样。water float(input(请输入用水量吨)) if water 0: print(用水量不合法请重新输入) elif water 10: fee water * 3 elif water 30: fee 10 * 3 (water - 10) * 5 else: fee 10 * 3 20 * 5 (water - 30) * 8 print(f水费为{fee} 元)来手动算两笔账验证一下。用水量8吨走water 10分支fee 8 * 3 24元。用水量25吨走elif water 30分支先算前10吨的30元再算15吨超额部分15×575元总计105元。用水量40吨走else分支30元加上20吨的中间档100元再加上10吨的最高档80元总计210元。逻辑链条清晰答案经得起手算验证。很多人第一次写这种分段计费问题会在第二个区间里把费用写成water * 5这就错了。因为分段计费的核心是“阶梯”——已经超过的部分按更高的单价计算不能把全部用水量都按高档单价算。这个错误在真实业务里会多收用户不少钱必须严肃对待。4.3 习题三输入三个数按从大到小排序这个题目非常经典也非常能折磨人。要求输入三个整数然后按从大到小的顺序输出。不用数组不用排序函数纯靠分支结构实现。朴素的思路是这样比较a和b把大的放在a里小的放在b里再比较a和c把大的放在a里小的放在c里这时候a已经是最大的了。然后比较b和c把大的放b里小的放c里。整个过程类似于“冒泡排序”手动版。a int(input(请输入第一个整数)) b int(input(请输入第二个整数)) c int(input(请输入第三个整数)) if a b: a, b b, a if a c: a, c c, a if b c: b, c c, b print(f从大到小排序{a} {b} {c})Python支持a, b b, a这种直接交换两个变量的写法非常方便。三个比较操作下来三个变量就从“输入顺序”变成了“从大到小排列”。来手动走一遍输入a5, b3, c8。第一轮a b即5 3不成立不变。第二轮a c即5 8成立交换后a8, c5。第三轮b c即3 5成立交换后b5, c3。最终a8, b5, c3排序成功。如果把题目扩展成四个数、五个数还这么手动比较的话组合数量会爆炸式增长。那时候就轮到排序算法登场了。但作为分支结构习题三个数的手动排序已经足够把比较逻辑和交换思想练得很扎实。这部分习题虽然简单但它教会我们的不只是语法而是一种“把现实规则翻译成代码”的思维模式。翻译的过程中最考验人的是把细碎的条件理清楚、把顺序排对、把边界处理好。5. 常见问题与代码调试心得5.1if条件里的赋值陷阱我之前在一个开发群里看到有人贴了一段代码if num 5: print(num 是 5)他本意是想判断num是否等于5却只写了一个等号。Python直接给出了SyntaxError在等号附近高亮提示。这个语法错误其实是Python在保护你——毕竟很多别的语言允许在条件里写赋值表达式结果就经常出现程序员错把写成导致逻辑判断永远为真或永远为假的问题。Python把这条路堵死了但新手如果不了解还是会困惑“为什么这里不能写赋值”。记住那句口诀“一个是赋值两个才相等”。5.2 缩进错误IndentationError与隐藏的逻辑错误缩进导致的报错分两种。第一种是明文报错的IndentationError: unexpected indent这种好办编辑器里红波浪线一标删掉多余空格就完事。第二种是“逻辑缩进错误”代码不报错但执行结果不对。比如num 5 if num 0: print(num 是正数) print(这句话也被缩进了属于if内部的代码) print(这句话没有缩进无论条件如何都会执行)如果为了美观或手滑把某一行本该在if外执行的代码误缩进了它就会变成“条件成立才执行”。这种bug最可怕的地方在于代码能跑、不报错但是行为不对。排查办法也很简单检查代码块的缩进层级每一层缩进都对应一层代码归属特别是在粘贴别人代码的时候最容易引乱缩进。5.3input()返回的是字符串不是数字新手最常见的运行时错误就是忘记input()返回的是字符串。直接拿字符串和数字比较Python会尝试比较如果两边类型不匹配比如5 10直接给你抛TypeError: not supported between instances of str and int。age input(请输入年龄) # 这里拿到的是字符串 if age 18: print(成年人)运行这段代码大多数情况会得到TypeError如果是Python 2时代的写法还可能产生匪夷所思的结果。正确做法是拿到输入后立刻转型age int(input(请输入年龄))5.4 条件顺序错了逻辑就走歪前面成绩等级判断已经演示了条件顺序的影响。现实业务里也有类似的问题。比如一个打折活动会员打8折非会员满100减20。如果先把“满100减20”写在前面那么会员也会先减去20再打8折结果全乱套。写分支结构时的一个重要习惯就是先把限制最严格、范围最小的条件写在前面再逐步放宽范围。或者反过来想把“必须立刻拦截的异常情况”排在最前面。比如前面闰年判断题里的“输入不合法”判断就应该放在最前面拦截掉无效数据再继续。5.5 终端中文输入法的引号问题这个坑特别无聊但害人不浅。写代码时输入中文输入法的全角引号“”代替英文半角引号Python会告诉你SyntaxError: invalid character “ (U201C)。解决方案只有一个编辑器里切换到英文输入法再写代码或者写完用代码格式化工具扫描一下。别问我怎么知道的谁还没在中文引号上翻过车呢。5.6 条件表达式写得啰嗦有新手会把“判断x是否在区间内”写成if x 10 and x 100:Python更地道的写法是链式比较if 10 x 100:两种写法都正确后者更贴近自然数学表达读起来也少一层代码噪音。没有强制要求换但如果写长表达式链式比较确实更舒服。6. 几个能立刻上手的练手场景6.1 用户登录模拟写一个最简单的用户名密码验证程序。预先设定一个用户名和密码用户输入后判断。如果用户名不存在就别再对比密码了如果用户名对了密码错了提示“密码错误”都对提示“欢迎登录”。username input(请输入用户名) password input(请输入密码) if username admin: if password 123456: print(欢迎登录) else: print(密码错误) else: print(用户名不存在)这个例子完整展示了if嵌套的应用场景也演示了“先拦截用户名再比对密码”的先后顺序。真实的登录验证逻辑会更复杂还包括密码加密存储、验证码校验、连续失败锁定等但骨架就是这么个判断结构。6.2 BMI指数计算器计算BMI指数公式是体重公斤除以身高米的平方。根据BMI值判断体型分类低于18.5偏瘦18.5到24正常24到28超重28以上肥胖。weight float(input(请输入体重公斤)) height float(input(请输入身高米)) bmi weight / (height ** 2) print(f您的BMI值为{bmi:.2f}) if bmi 18.5: print(偏瘦) elif bmi 24: print(正常) elif bmi 28: print(超重) else: print(肥胖)这段代码跟成绩等级评定的结构如出一辙。bmi:.2f是格式化输出的写法保留两位小数。这个场景在健康类小程序中很常见也是分支结构最经典的“区间判定”应用。6.3 石头剪刀布游戏这是分支结构的一个小型综合应用。玩家输入“石头”、“剪刀”或“布”程序随机出一个然后判断谁赢。需要先导入random模块用random.choice()从列表里随机选一个然后通过多层条件判断比较输赢。import random player input(请输入石头、剪刀或布) computer random.choice([石头, 剪刀, 布]) print(f你出的是{player}电脑出的是{computer}) if player computer: print(平局) elif (player 石头 and computer 剪刀) or \ (player 剪刀 and computer 布) or \ (player 布 and computer 石头): print(你赢了) else: print(你输了)胜利条件的写法是三个“玩家出X且电脑出Y”的or组合或者“反之亦然”。这里还能引出小技巧把所有胜负关系抽象成一个字典零散的条件判断就会变成一行字典查询。这个进阶思路可以等你基础打牢了再研究。上面这几个练手场景难度都不大但都是分支结构在真实小项目里的浓缩。做完这些你对if分支的掌握基本就过关了。7. 一些过来人才懂的实操建议7.1 先画流程图再写代码写复杂分支逻辑之前先画一个简单的流程图。我见过太多初学者一上来就闷头写代码写到一半逻辑乱了又回头删。画流程图的好处是它能强制你把“什么条件下走什么分支”在每个节点上都想清楚避免写代码时只顾着一个分支而忘了其他分支。流程图工具不讲究纸上画都行。用最简单的框和箭头画完后你再看代码结构一目了然。7.2 边界值一定要单独测写分支结构的时候最容易出问题的地方不是“中间部分”而是“边界值”。比如判断成绩等级时89分、90分、91分之间的界线到底在哪边判断水费分段时10吨和30吨这两个节点属于哪一段这些问题在写代码的时候就要在脑子里过一遍写完用测试代码故意输入边界值验证。我现在写任何包含区间判断的代码都会拿几个关键节点先算一遍“等于下界”“等于上界”“恰好越过界线”这三种情况一个不落。这个习惯帮我避免了很多线上事故。7.3 能用字典就不要用一堆if如果再往前走一段你会发现很多if / elif其实是在做“映射”——输入一个键输出一个值。比如把数字1到7映射到“星期一”到“星期日”这种场景用if结构写出来又长又容易错用字典更干净weekdays { 1: 星期一, 2: 星期二, 3: 星期三, 4: 星期四, 5: 星期五, 6: 星期六, 7: 星期日, } day int(input(请输入数字)) print(weekdays.get(day, 无效输入))这里还用到了get()方法如果day不在字典里就返回默认值“无效输入”。这一行代码替代了7个if分支的工作量。如果你发现自己在写超过四五个elif就该停下来想想是不是有更优的数据结构可以用了。7.4 写代码不仅是给机器看的更是给人看的最后一条建议可能听起来有点虚但在团队协作里特别重要。分支结构看似简单一旦嵌套多了、条件复杂了别人看你的代码就像看迷宫。为了不让未来的自己更倒霉的是你的同事面对迷宫头大尽量做到条件语义清晰、命名直白、能用逻辑运算符合并的地方就合并、能用早返回就早返回。代码是写给人看的只是顺便能被机器执行而已。我在实际带新人的过程中发现能把分支写得“平”和“顺”的人往往比能写“炫技嵌套”的人更靠谱。因为前者更在意可维护性这是一种职业素养不只是一个语法熟练度的问题。
返回列表