🧠 第三章 编程语言
📄 一句话概括

链式比较 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 秒实验

  1. 把业绩区间的四个档位改成三个,重新跑一遍命中统计。
  2. 用 if not s 和 if s != '' 各写一遍判空,喂一个 None 进去看谁崩。
  3. 想一想:为什么规则表要从窄条件写到宽条件?

常见误区

  1. 「== 能判空」——None == '' 是 False,判空就漏了。
  2. 「链式就是展开写」——中间值求值次数不同,有副作用时结果不一样。
  3. 「or 和 and 意思差不多」——1 < 15 or 15 < 10 恒为真。
自测三问(点开对答案) 1. `'0'` 和 `[0]` 在 `if` 里算真还是算假? —— 都算真——它们不是空的,只有空容器和零值才算假。 2. 链式比较比展开写好在哪? —— 中间那个值只求值一次,避免重复计算和副作用。 3. 为什么 `elif` 的顺序有讲究? —— 命中第一个为真的分支就跳出,范围大的写前面会让后面的进不去。

条件判完了,接着让它重复做——循环语句一次处理一批数据。

相关笔记