链式比较 1 < 5 < 10 是 True、1 < 15 < 10 是 False,中间那个数只求值一次。
哪些值算假?0/''/[]/{}/None 都算,但 '0' 和 [0] 算真。
上一节把数算出来了,这一节让程序根据结果走不同的路。 业务规则几乎全部落在条件语句里,写错一个边界就错一批数据。
一、三种分支,一个入口
if/elif/else 从上往下判,命中第一个为真的分支就跳出去,后面的不再看。
Demo 用三组数演示:3 与 5 给出「y 大」,5 与 3 给出「x 大」,5 与 5 给出「一样大」。
这个「命中即跳出」很重要:把范围大的条件写在前面,后面的分支就永远进不去。规则表要从窄到宽排。
二、链式比较:中间只算一次
1 < 5 < 10 是 True,1 < 15 < 10 是 False。
它等价于 1 < 5 and 5 < 10,但有个关键差别:链式写法里中间那个数只求值一次。
如果中间是个函数调用,差别就大了:链式只调一次,展开写会调两次,有副作用时结果不同。
还有一处易错:把 and 写成 or。1 < 15 or 15 < 10 是 True——因为第一个条件就成立了。
看着像链式,语义完全反了。
三、哪些值算假
if 后面不一定是比较表达式,任何值都能放。
Python 对「真假」的规矩是:空的、零的、None 的算假,其余算真。
Demo 把十种值扔进 bool():0、0.0、''、[]、{}、()、None、False 全是 False。
但 '0'(内容是一个零字符的字符串)和 [0](含一个零的列表)都是 True——它们不是空的。
所以判空写 if not s 最稳。写成 if s != '',遇到 None 就漏了;
写成 if len(s) > 0,遇到非序列就抛异常。
四、三目与分支统计
简单的二选一可以写成一行:'及格' if score >= 60 else '不及格'。Demo 用 82 分算出 '及格'。
嵌套也能写,Demo 用 '优' if >= 90 else ('良' if >= 75 else '中') 得到 '良'。
但嵌套超过两层就该改成 if/elif,否则没法读。
Demo 还统计了 100 个业绩值落在四个区间的次数:26/26/24/24。
这个统计本身比条件语句更有用——它告诉你规则表是不是被某一档垄断了。
写规则时先跑一遍分布,再看命中率。只看代码看不出「90% 的数据都走了第一个分支」这种事。
五、动手 Demo:判大小、判真假、判分支走哪边
用三组数走一遍 if/elif/else;验证链式比较与展开写法;把十种值依次扔进 bool() 看真假;
再对 100 个业绩值做一次分支命中统计;最后演示三目与嵌套三目。
if x > y:
r = 'x 大'
elif x < y:
r = 'y 大'
else:
r = '一样大'
print(1 < 5 < 10, 1 < 15 < 10) # True False
print(1 < 5 and 5 < 10) # 等价写法
for v in (0, 0.0, '', [], {}, (), None, False, '0', [0]):
print(repr(v), bool(v))
r = '及格' if score >= 60 else '不及格'
实跑输出:
--------------------------------------------------------------------
条件语句:判大小、判真假、判分支走哪边
--------------------------------------------------------------------
比大小:
输入 结论
--------------
3 与 5 y 大
5 与 3 x 大
5 与 5 一样大
链式比较 1 < 5 < 10 True
链式比较 1 < 15 < 10 False
等价写法 True
链式不是两次独立比较,中间那个数只求值一次——写错成 or 就全 True。
哪些值算「假」:
值 bool(值)
---------------
0 False
0.0 False
'' False
[] False
{} False
() False
None False
False False
'0' True
[0] True
注意最后两行:字符串 "0" 和列表 [0] 都是真。判断「有没有内容」
用 if not s,别写 if s != ""——后者遇到 None 就废了。
分支命中统计(100 个业绩值,看落到哪档):
1~50 ############################## 26
51~100 ############################## 26
101~150 ############################ 24
151~200 ############################ 24
合计 100 次
三目写法 '及格'
嵌套三目 '良'
三组比较分别给出「y 大」「x 大」「一样大」,说明 elif 的存在正是为了处理第三种情况。
漏掉 else,相等的那些会被静默忽略。
链式两行:True 和 False;等价写法那行也是 True。两条路结果一样,但链式只算一次中间值。
十种值的真假一眼看完:前八个 False,'0' 和 [0] 是 True。
「非空即真」这条规则,比记清单更可靠。
分支统计 26/26/24/24,四档几乎均分。如果某一档吃掉 90%,就该检查档位划分是不是合理。
三目两行分别是 '及格' 和 '良'——一行写完二选一,嵌套别超过两层。
30 秒实验
- 把业绩区间的四个档位改成三个,重新跑一遍命中统计。
- 用
if not s和if s != ''各写一遍判空,喂一个None进去看谁崩。 - 想一想:为什么规则表要从窄条件写到宽条件?
常见误区
- 「
==能判空」——None == ''是 False,判空就漏了。 - 「链式就是展开写」——中间值求值次数不同,有副作用时结果不一样。
- 「
or和and意思差不多」——1 < 15 or 15 < 10恒为真。
自测三问(点开对答案)
1. `'0'` 和 `[0]` 在 `if` 里算真还是算假? —— 都算真——它们不是空的,只有空容器和零值才算假。 2. 链式比较比展开写好在哪? —— 中间那个值只求值一次,避免重复计算和副作用。 3. 为什么 `elif` 的顺序有讲究? —— 命中第一个为真的分支就跳出,范围大的写前面会让后面的进不去。条件判完了,接着让它重复做——循环语句一次处理一批数据。
- ☐ (本节完,下一节 3.2.6 使用Python循环语句:输出一系列数字)