ARTICLE DETAIL

资讯详情

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

Python条件判断语句精讲:if/elif/else与布尔逻辑实战

Python条件判断语句精讲:if/elif/else与布尔逻辑实战 从“顺序执行”到“程序会决策”Python的条件判断语句为什么值得认真学写Python写过一阵子的人多半都有过这种体验代码能跑通循环也会写但业务逻辑一复杂程序就开始“不听话”了——该拦截的非法输入没拦住该走的分支走了错路好几个if堆在一起自己都看晕。问题的根源往往不在语法本身而在“条件判断”这一课上没有真正吃透。刚开始学Python的人最容易把if理解成“如果……就……”但这个理解太浅了。条件判断是程序从“机械执行”走向“有逻辑”的分水岭是三大程序控制结构顺序、选择、循环里最先让你感受到“代码长脑子”的部分。这篇博文就围绕Python的条件判断语句展开把if、elif、else、布尔逻辑、进阶写法、实际工程里的坑一次讲透配合可以直接复制运行的代码示例。不管你是刚装好Python还没写满100行的新手还是已经会用基础语法但被分支逻辑绕晕的自学者这篇文章都适合你。我会把自己踩过的坑和常用的排查手段一并写出来看完之后你写出来的条件判断不敢说百分百没bug至少不会在阴沟里翻船。1. 从“顺序执行”到“程序会决策”条件判断到底解决了什么问题1.1 代码不是一路跑到黑的——三大控制结构里选择结构是第一步很多人学编程的第一个程序是print(hello world)第二三个可能就是print几行别的东西。这跟小学生写作文一样一行一行从上往下写程序也一行一行从上往下跑这就是所谓的“顺序结构”。顺序结构当然简单但现实世界里几乎没有哪件事是纯线性的。举个例子早上出门前你会不会看天气如果下雨就带伞不下雨就不带如果气温低于10度就穿厚外套否则穿薄外套。这种“根据条件走不同路线”的思考方式放到程序里就是“选择结构”。Python里的选择结构核心就是if、elif、else这三个关键字。平时大家口中说的“条件判断语句”指的就是它们。顺序结构是程序的骨架选择结构是程序的血肉循环结构是程序的耐力。如果把程序比作一个流水线工人顺序结构就是它按部就班地干一个工序又一个工序条件判断就是它面对来料时先质检合格的走合格通道不合格的走退货通道循环就是一批活没干完就反复干干完才停下。对Python初学者来说条件判断学得好不好直接决定你能不能写出“有脑子”的脚本——判断用户输入合不合法、检查文件存不存在、根据成绩划分等级、模拟游戏里角色是否存活底层全都是条件判断。1.2 一切判断的基础布尔值、比较运算符与Python的“真真假假”条件判断要工作首先得有“条件”。那什么是条件在Python里条件最终都会被计算成一个布尔值True或者False。这两个值不是普通的字符串它们有专门的类型叫bool。Python里大多数需要做选择的地方都会拿一个布尔表达式说话。布尔表达式最常见的来源是比较运算。Python的比较运算符总共就那么几个但用法上有不少容易搞混的判断两个值是否相等!判断两个值是否不相等、、、这组用来比大小。这里我单独啰嗦一句很多新手踩的第一个坑就是把赋值号当等于号用在if后面写if score 60然后报错一脸懵。if后面要的是“条件”是一个会产生True或False的表达式赋值语句不会产生布尔值所以语法上直接不允许这么写。比较运算符用起来很简单但判断字符串、列表、字典这类复合类型时要理解“相等比较”和“身份比较”的区别这个我放到后面进阶部分细讲。现在先把基础打牢条件判断的本质就是“算出一个布尔值然后根据它是True还是False决定走哪个分支”。2. 核心语法写好if/elif/else的每一个细节2.1 最简单的if条件为真才执行后面的代码Python里最基础的条件判断就一行if加一个冒号下面缩进写执行语句score 85 if score 60: print(及格了)这段代码的阅读理解很简单如果score大于等于60就执行print(及格了)否则什么都不做。但有几个语法细节新手一定会碰到第一if那一行末尾的冒号不能丢丢了直接SyntaxError第二print前面必须有缩进Python用缩进来划定“哪些代码属于这个if”。缩进通常是4个空格这是PEP8推荐的风格。同一个代码块里缩进必须一致不能这次用2个空格下次用3个。为什么Python不像C、Java那样用花括号来包代码块非要用缩进因为设计者觉得代码的视觉层次就是逻辑层次强迫程序员统一缩进写出来的代码才整齐。这种设计对新手其实更友好你不需要跟大括号配对的破事较劲代价就是你必须老老实实把缩进敲对。IDLE、VS Code这类编辑器只要开了“Tab键自动转4空格”基本不会出问题但我见过不少老一辈程序员是用文本编辑器直接按Tab键写Python的一旦他们和空格派混编同一个文件那个酸爽……从工程角度看if的语句块里可以有多条语句它们都得缩进相同的空格数。哪怕程序逻辑上需要空一行建议也保持同样的缩进结构只留空行不要在里面塞乱七八糟的代码。我见过为了看起来整齐故意把缩进多敲几层的行为那是自己给自己挖坑——Python解释器只管你的缩进是否一致不会帮你“看出”意图。2.2 if/else二选一处理相反的情况只判断“及格了然后打印”还不够很多时候你要把“不满足条件”的情况也接住。score 42 if score 60: print(及格了) else: print(没及格下次加油)else不需要接任何条件它表示“前面if的条件不成立时走这里”。这个结构看起来理所当然但隐藏着一个设计习惯else分支里的代码往往比if分支里的代码更需要想清楚边界。判断成绩时你写了score 60的隐含条件但如果score是字符串、是负数、是None呢else并不是“所有其他情况都是你心里想的那种”它只是“if条件为假就执行这里”。所以真正工程里我习惯在else分支里再做一次防御式判断后面实战部分会写到一个完整的例子。初学阶段别小看else这种“对称结构”它是理解程序分支神经回路的关键。没有else的if是单向阀只有一种情况会触发附加逻辑有了else程序才算真正在两条路上做了选择你的代码才开始有“决策”的味道。2.3 elif多分支决策的优雅写法现实问题很少只有两个分支。成绩要分优秀、良好、中等、及格、不及格商品要按库存量显示不同提示游戏里要根据玩家生命值判断状态……这时候就需要elif。score 76 if score 90: grade 优秀 elif score 80: grade 良好 elif score 70: grade 中等 elif score 60: grade 及格 else: grade 不及格 print(f你的等级是{grade})elif是“else if”的缩写本质就是“前面的条件不满足时再试下一个条件”。有两点必须讲清楚第一elif分支是按顺序从上到下判断的Python找到一个满足条件的分支后会执行完该分支并直接跳出整个if-elif-else结构。也就是说如果score95它会进入第一个分支输出“优秀”后面的elif一概不看。这个特性决定了写多分支时条件的顺序非常重要区间判断要从大到小排或者从小到大排绝不能随意乱序。第二elif可以有任意多个最后的else是可选的。如果在所有条件都不满足的情况下你真的没什么要做的可以不加else但这时候代码的可读性会下降阅读者会疑惑“难道有什么情况被漏掉了”所以我个人的经验是多分支结构里能写else就写else哪怕你只想在else里留一句注释说明“理论上到不了这里”也比你什么都不写强。这里可能会有人问elif和多个独立的if有什么区别同样是判断score在不同区间写成三四个独立的if行不行行但行为完全不同。独立的if每个都会判断一遍即使第一个满足后面的还会继续判断而elif链里只要有一个满足就刹车了。看代码的人读到多个独立if时会以为你要的是“多个条件可以同时成立”的效果用elif链则明确表达“这几个分支是互斥的只能进一个”语义清晰很多。2.4 缩进和冒号新手最容易翻车的两个语法细节围绕if/elif/else的三个语法点里冒号和缩进是两大事故高发区。漏写冒号解释器会直接报错这个还好防编辑器里红色波浪线会告诉你。真正阴险的是缩进不一致你知道要用缩进但不知道“多少缩进才算同一个块”。我见过最经典的报错是IndentationError: unexpected indent以及更头疼的TabError: inconsistent use of tabs and spaces in indentation前者表示缩进层次不对后者是Tab和空格混用。如果你用的编辑器把Tab显示成和4个空格一样的宽度混用往往肉眼看不出来。解决方案很暴力编辑器设置里把Tab键自动替换成4个空格从此你的代码里永远只有空格。这个习惯我强烈建议从第一天学Python就养成别抱侥幸心理。还有一类可能让人抓狂的情况是看起来同一个块有的行用了4个空格有的行用了5个空格多数是自动补全或者复制粘贴带进来的Python不会容忍这种“差不多”它非常较真。调试这类问题就一个诀窍选中代码块看编辑器右侧的空白或者直接打开“显示空格和制表符”的选项VS Code底部工具栏里就能显隐。这和查密码拼写一样越早发现越好。3. 让条件更聪明布尔逻辑、成员判断、身份判断与一行式决策3.1 and、or、not把多个条件组合成一个决策单独一个条件往往不够用。比如判断闰年完整规则是“能被4整除但不能被100整除或者能被400整除”。翻译成人话就是一个组合条件。year 2024 if (year % 4 0 and year % 100 ! 0) or (year % 400 0): print(f{year}是闰年) else: print(f{year}不是闰年)这里的and和or是Python的“逻辑与”和“逻辑或”and要求两边同时为True才整体为Trueor要求只要有一边为True就整体为True。not则是一元操作符把True变成FalseFalse变成True。它们和生活中的“并且”“或者”“不是”几乎一一对应很容易理解。但里面有个坑是初学的人大都会踩的Python的and和or并不是纯粹返回布尔值而是有“短路求值”的行为并且会返回参与运算的某个值本身。举个例子a and b时如果a是False整个表达式直接返回a根本不会去计算b如果a是True则结果就是b的值。or同理。这个特性在工程上常被用来写默认值比如name input_name or 游客意思是如果input_name为空字符串就让name变成游客。但如果你刚学不熟悉这个机制我建议先老老实实写成if input_name: name input_name else: name 游客等读得懂别人写的短路赋值时再去享受那种一行式的简洁。逻辑运算优先级也需要注意not的优先级最高其次是and最后是or。如果你写的是复杂的混合条件多打一层括号不吃亏。有人觉得括号多显得菜但我宁可看到一个括号清楚的条件也不想去猜谁跟谁先结合。3.2 成员判断in、身份判断is与链式比较除了比较运算符Python还提供了好几个能生成布尔值的表达方式用得好会让代码像英文句子一样自然。第一个是in判断某个元素是否在容器里。name alice allowed_names [alice, bob, charlie] if name in allowed_names: print(是团队成员)这个写法比你去写name alice or name bob or name charlie舒服得多而且列表越长优势越大。还可以配合not inif name not in allowed_names直接在条件里取反不用在外面再包一层not。第二个是is判断两个变量是否指向同一个对象。这个必须重点讲清楚因为很多人拿is当用。比较的是“值相等”is比较的是“身份相等”相当于问“这两个是不是同一个东西”。对整数小数字、短字符串这类情况Python解释器有缓存机制is比较偶尔也能碰巧对这就让人产生错觉。但一旦遇到列表、字典、大整数is和的结果往往不一致。判断一个对象是否为None行业惯例是用is None比如if data is None:。这不是语法强制的是大家在工程里约定俗成的正确姿势因为None是个单例对象用判断也不是不行只是不地道。第三个容易被忽略的写法是链式比较Python允许把多个比较运算符串起来用。别的语言大多得写age 18 and age 60Python可以直接写18 age 60语义一目了然。我写成绩区间时特别喜欢用这个后面实战部分会看到。3.3 三元表达式用一个表达式完成二选一赋值有些时候if-else的作用仅仅是给一个变量赋不同的值值本身不复杂。这时候用完整的多行结构有点小题大做Python提供了“三元表达式”也叫条件表达式age 17 status 成年 if age 18 else 未成年 print(status)语法顺序是“值1 if 条件 else 值2”意思就是条件成立时取“值1”不成立取“值2”。很多从C、Java转过来的人会不适因为C的写法是条件 ? 值1 : 值2顺序不一样。我更倾向把Python的三元表达式读成英文“A if condition else B”本来就是一句自然语言顺着读就好。使用三元表达式时要注意一个原则它适合“两边都是简单的赋值或表达式”不适合嵌套。别写出status A if x 0 else (B if x 0 else C)这种套娃阅读成本瞬间爆表。这种连续区间判断老老实实写多行elif所有人都看得懂。3.4 一个扩展Python 3.10以后可以用的match语句如果你用的是Python 3.10及以上版本还会接触到一个叫match的新语法它常被看作类似其他语言里的switch-case。match语句从功能上和if-elif链有重叠但它更强调“模式匹配”的直觉。def handle_command(command): match command: case start: print(开始) case stop: print(停止) case _: print(未知命令)最后那个case _相当于else接住所有不匹配的情况。match语句初学时可以不急着学但看到别人代码里有至少要知道它等价于一个多分支判断。项目里如果只是做简单的值匹配match比一串elif看起来更整齐但涉及区间比较、复杂条件时还是if-elif链更灵活别硬套match。4. 实操过程用条件判断动手写一个“成绩等级查询”程序4.1 需求拆解与方案选型聊了这么多语法接下来把知识揉在一起做一个能跑的小程序。目标很简单用户输入一个成绩0到100之间的数字程序输出对应的等级。但“输入”两个字背后藏着很多边界事故这才是真实工程和练习题最大的区别用户不一定会老老实实输个合法数字给你。我把需求拆成几步接收用户输入可能是85、-20、abc甚至直接回车。校验输入是否是一个数字不是就提示重新输入。校验数字是否在0到100范围内不在就提示。按标准划分等级90及以上优秀80-89良好70-79中等60-69及格60以下不及格。把结果打印出来而且要能连续查询直到用户主动退出。这个需求正好把if、elif、else、in、比较运算符、类型转换、循环全部串起来是练手的好题材。4.2 写出第一版代码校验与分级先看核心的判断部分我刻意把校验逻辑写得直白一点便于理解while True: raw input(请输入成绩输入q退出) if raw.lower() q: break if not raw.replace(., , 1).isdigit(): print(输入无效请输入数字) continue score float(raw) if score 0 or score 100: print(成绩需要在0到100之间) continue if score 90: grade 优秀 elif score 80: grade 良好 elif score 70: grade 中等 elif score 60: grade 及格 else: grade 不及格 print(f成绩 {score} 分等级{grade})这段代码里有几个值得讲透的点。第一个是raw.replace(., , 1).isdigit()。这段很典型我想单独拆一下isdigit()只能判断“字符串全是数字”它不认识小数点。所以如果直接对85.5调isdigit()结果会是False那用户输入带小数的成绩就会被误判成非法。解决思路就是把小数点和后面可能跟着的数字一起解决掉把字符串里最多一个小数点替换成空字符串剩下的部分还能isdigit()就说明它要么是纯整数、要么是带小数点的数字。这个方案不是万能的它放过了类似85.这种字符串里面还有坑但作为入门阶段的教学例子它的思路比它的完备性更重要。等学完异常处理try/except你自然会有更好的写法。第二个值得聊的是分支顺序。我故意把90写在最前面然后一路降到60最后else接“不及格”这符合“从高到低”的自然逻辑。如果你把条件顺序写成if score 60:不及格elif score 70:及格……也是可以的但阅读者的习惯是从高分看起所以我推荐大多数人按“高分优先”的顺序排列区间分支。第三个是while True配合break、continue实现连续查询。这套组合可以说是Python交互式脚本的万金油。break表示退出整个循环continue表示跳过本次迭代、直接进入下一次输入。注意continue在if块里使用时要确认不会造成死循环这里continue之后会重新input所以没问题。4.3 跑起来的实际效果与边界测试这一段我建议你亲手跑一遍光看不练看不出门道。我先列几个典型输入请输入成绩输入q退出85 成绩 85.0 分等级良好 请输入成绩输入q退出59 成绩 59.0 分等级不及格 请输入成绩输入q退出abc 输入无效请输入数字 请输入成绩输入q退出-30 成绩需要在0到100之间 请输入成绩输入q退出q看到没非法输入都被拦在外面程序不会因为用户输了个abc就崩溃。这就是条件判断在真实程序里最重要的价值——它不是写给人看的“如果这样就这样”而是程序边界的守护者。4.4 给程序加一点点“工程味”函数化改造前面那版把所有逻辑揉在while循环里跑通没问题但结构上不算优雅。如果我后续要扩展功能比如把等级判断复用到另一个模块里就尴尬了。这时候把核心逻辑抽成函数是比较好的习惯def get_grade(score): if score 90: return 优秀 if score 80: return 良好 if score 70: return 中等 if score 60: return 及格 return 不及格 while True: raw input(请输入成绩输入q退出) if raw.lower() q: break if not raw.replace(., , 1).isdigit(): print(输入无效请输入数字) continue score float(raw) if score 0 or score 100: print(成绩需要在0到100之间) continue print(f成绩 {score} 分等级{get_grade(score)})这里有个细节值得单独点出来函数里的多个if没有用elif每个if后面直接return。这其实是一种很常见的写法因为只要命中一个条件就返回了后面的if根本不会再执行。它和elif的效果是一致的但少了一层缩进代码看起来更扁平我写小型判断函数时特别爱用这个风格。不过这会带来一个要求每个分支都必须有return等于把“每个情况都要有结果”变成硬约束比else更安全。养成这个习惯后你能减少不少漏掉分支的bug。5. 常见问题与排查技巧实录那些年我踩过的条件判断的坑5.1 最容易翻车的5种写法错误我把这几年辅导新人时最常遇到的几类问题汇总成一个速查表典型问题报错现象正确写法if后写了个而非条件里出现赋值有的版本直接SyntaxErrorif score 60:忘记if行末的冒号SyntaxError: invalid syntaxif score 60:Tab和4空格混用TabError: inconsistent use of tabs and spaces in indentation统一用4空格elif错误写成else ifSyntaxError: invalid syntaxelif score 80:input()拿到的字符串直接和数字比TypeError: not supported between instances of str and int先float(input())转换第一个坑值得展开讲if score 60这个错误在Python 3.8及以后版本通常不会“默默生效”而是直接SyntaxError原因就是Python不允许赋值语句出现在布尔表达式的位置。但很多从C语言转过来的人会惯性写出等号早期C编译器只是警告嘴上说“你确定是赋值吗”实际还是按真值判断到了Python这里就零容忍。我建议新手把读成“等于”把读成“赋值为”这样至少写出来之前心里有数。input()的坑也很典型input返回的永远是字符串。你把85跟60比较“大于等于”Python是拒绝执行的错误信息会告诉你不能在字符串和整数之间比较大于等于。解决办法就是开头加一行score float(input(...))。这里连带出一个习惯做转换时最好把转换放在校验前还是校验后我上面的示例是先校验字符串格式再转换数字这一步其实兼顾了安全性和可读性如果你先float()再校验遇到非法输入会在转换那行直接抛出异常。初学者还没学try/except所以我先用isdigit加replace的土办法挡非法输入等学了异常处理再换成更地道的try方案。5.2 分支顺序写错一个顺序整个逻辑悄悄出错有一种bug不会报错但结果永远是错的这就是分支顺序问题。看下面的代码score 95 if score 60: grade 及格 elif score 90: grade 优秀 print(f等级{grade})逻辑上“优秀”比“及格”高但你把“60”写在前面95分进来第一个条件就中了直接输出“及格”后面的“优秀”根本没机会执行。这种bug特别讨厌程序能跑输出也不报错就是等级完全错乱。调试时往往要盯好久才会发现是顺序问题。我的经验是做区间型判断时要么从宽到窄要么从窄到宽选一种固定顺序并写清楚注释。比如成绩判断我习惯从高分往低分写90、80、70、60、else这样小于60的数自然落在else里。反过来从低分往高写也行判断逻辑等价只是阅读习惯不同。真正要避免的是东一个西一个想到什么条件就写什么条件。还有一点数值区间判断时尽量用“”而不是“”避免把边界值漏掉比如你想让90分算优秀就别写score 90。5.3 空值和空容器判断if not、is None、len()之间怎么选条件判断里另一个高频争议点就是“怎么判断一个变量是不是空”。先统一概念Python里“空值”和“假值”不完全是一回事。None是唯一的空对象标志而空字符串、空列表[]、空元组()、空字典{}、数字0在布尔语境下都会被当成False。新手最常见的困惑是if data is None: # 我没判断出空字符串的情况 if not data: # 把0、空字符串、空列表全当“通过”了但如果data0业务上合法呢这两者的区别必须掰扯清楚。如果你要判断的是“这个值是不是明确表示没有数据”用is None。如果你要判断的是“这个值在逻辑上是不是空的/假的”比如用户没输入内容用if not name非常自然。但如果你要处理的数据可能是数字0而0在业务上是合法输入千万别用if not data否则你会把0错当成非法输入拦掉。正确姿势是显式判断类型或做更多条件比如if data or data is None: print(缺少数据)顺带讲一个细节有些新手喜欢写if len(data) 0来判断“非空”这个写法不算错但在Python里不太地道直接if data或if not data更简洁代码也更“pythonic”。不过你要是为了明确表达“容器里有没有元素”用len()其实也无伤大雅。我自己会看场景判断结果只是true/false时用if data需要知道具体元素数量时用if len(data) 0两回事。5.4 浮点数比较为什么0.1 0.2 0.3会返回False这个坑可以排进“新手最想摔键盘的瞬间”前五名。在Python里执行0.1 0.2 0.3你会得到False而不是直觉上的True。原因不在条件判断而在浮点数的存储方式计算机用二进制存储小数0.1这样的十进制小数没办法被二进制精确表示只能在内部存一个近似值。两个近似值相加之后拿到的还是一个近似值跟0.3的近似值比较时它们就不相等了。遇到这类“浮点相等”判断时我给你的建议很简单别用判断浮点数改为判断它们的差是否足够小。通常我会设置一个极小阈值比如if abs((0.1 0.2) - 0.3) 1e-9: print(在误差范围内相等)日常写脚本如果你需要的是“精确到什么小数位”也可以用round先四舍五入再比较if round(0.1 0.2, 1) 0.3。需要提醒的是round的比较在高精度场景也不万能但入门脚本里够用。如果你将来接触金额计算、金融系统一定要学decimal模块那种场景下浮点数不是“差不多就行”而是“绝对不能错”。5.5 条件写得太长的三个坏味道和一个改造思路条件判断用多了之后你会发现有些if条件长得离谱比如if (a 0 and a 100) or (b 0 and b 100) and not flag:读上三遍头就大了。这类代码有三个坏味道第一逻辑运算优先级不清读者不敢乱猜第二条件本身太长一眼看不出判断意图第三一旦业务逻辑变化改起来牵一发动全身。我的改造思路很朴素给复杂的条件命名。把一段布尔表达式从if里抽出来赋值给一个语义化的变量is_valid_range (a 0 and a 100) or (b 0 and b 100) is_allowed is_valid_range and not flag if is_allowed: ...这样条件本身变成了一段“注释代码”读起来就像在读英文句子而不是在解谜。一个人维护的项目可能无所谓但代码迟早要发给别人看或者你三个月后再回来看你会感谢当时那个愿意给条件起名字的自己。一点实操后的私人体会我用了这些年Python如果要挑选一个“最值得一开始就学扎实”的知识点条件判断当之无愧。循环结构再复杂核心也就是个重复执行而条件判断才是让你把现实世界的规则翻译给机器的过程。写成绩判断、写输入校验、写业务状态流转本质上都在做同一件事帮程序建立边界让它知道什么时候该往哪走。第一次写出一个能拦下所有非法输入、每个分支都正确输出的脚本时的成就感值得你把这些细节耐心过一遍。最后再分享一个小技巧写条件判断时先把“不合法的情况”都放在最前面处理用continue或return挡掉最后剩下的全流程自然是干净的主逻辑。这个“早返回”风格的思路普通文档里很少明说但实战中帮我省下了大量排查时间。你可以试一版不做任何校验的脚本再对照着加了边界判断的版本感受一下程序从“会跑”到“稳跑”的差别。
返回列表