跳转至

四类运算 — 赋值、算术、比较、逻辑

这一章给变量配上武器。 前面你只能把值存起来再原样取出来; 这一章起你能算它们、比它们、把好几个条件拧成一个新的条件。 原书把运算分成四组,我们一组一组过,每组都走一遍主线例子。

1. 这一章在全书链条里的位置

第 03 章回答了「值是什么」,这一章回答「值能怎么摆弄」。四组运算恰好对应程序的 四种基本动作:存(赋值)、算(算术)、判(比较)、合(逻辑)。 其中「判」和「合」的产物是布尔值 True/False——它们单独看没用, 但它们是第 07 章分支(「如果……就……」)的燃料,没有它们分支无从点火。

2. 顶层全景:四组运算一张表

家族 干什么 运算符 产出什么
赋值 把值的名字定下来 / 改 = 以及 += 等 无(动作)
算术 数学计算 + - * / // % ** 数(int 或 float)
比较(关系) 比大小、比相等 == != > < >= <= 布尔值(True/False)
逻辑 把布尔值拧在一起 and or not 布尔值

这是原书最后一张总结表(Table 4.2)的骨架1。下面逐组讲透。

3. 第一组:赋值 — 第 03 章那件事的正名

= 在 Python 里不是数学的「等于」,是「把右边的值交给左边的名字」2。 书在这里把第 03 章的「引用」心智模型又夯实了一遍:

x = 5    # x 指向内存里存 5 的位置(书里的原话:把 5 的「地址」交给 x)
y = x    # y 指向 x 所指向的同一个位置——此刻 x 和 y 是同一个 5 的两个名字
x = 6    # x 改指向 6 的位置
print(y) # 仍然输出 5:y 还指着原来的位置,纹丝不动

关键点:x 变了,y 为什么不变? 因为 x = 6 是把 x 这个名字的指向整个换掉, 不是把原来那个 5 改成 6;y 的指向没人动过3。

一次性给多个变量赋值

x, y = 5, 6

等价于 x = 5 再 y = 6。书里的执行顺序值得记住: 先算右边(5 和 6),再按顺序分给左边4。 练习里立刻用上了它:name, age = input('What is your name: '), int(input('What is your age?')) ——问姓名、问年龄(顺手 int() 转掉),一行收工,输出 Neo is 18 years old.5。

补充(书在总结表里才出现):+=、-=、*= 这些增强赋值是 x = x + 1 的 速写——x += 1 就是「把 x 加一再存回 x」6。本书正文没有单独展开, 但总结表列了全部七种(+= -= *= /= %= //= **=)6,看到认识即可。

4. 第二组:算术 — 七个运算符

原书列了七个算术运算符7:

运算 写法 例子(a=5, b=2) 结果
加 a + b 5 + 2 7
减 a - b 5 - 2 3
乘 a * b 5 * 2 10
除 a / b 5 / 2 2.5(float,哪怕整除也是)
整除(地板除) a // b 5 // 2 2(商向下取整,丢余数)
取余 a % b 5 % 2 1
幂 a ** b 5 ** 2 25(5 的平方;** 读作「的……次方」)

这一组就是主线例子的主角,原书的演示 a = 5; b = 2 七连打,上面表格的 「例子/结果」列逐字来自演示输出8。

三个最容易翻车的点:

  1. / 永远交出 float:哪怕 10 / 2 数学上等于 5,Python 也给你 5.0。 想要整数结果用 //8。
  2. // 是向下取整不是向零取整——对正数无所谓(5 // 2 = 2),对负数 -5 // 2 得 -3(向下)而不是 -2。书里没讲负数,这是边界,先记着有这个坑9。
  3. % 的威力在「分组」:一个数模 4 余几,决定它属于哪一组——判断闰年、 判断奇偶全指望它(下面主线例子见真章)。最常用的一招:n % 2 == 0 为真 就是偶数,为假就是奇数——「模 2」把全体整数分成两类,这个式子你以后会 写几十遍。

主线例子补遗:一组数挨个分类

把 a = 5, b = 2 的七连演示再走一遍,这次盯的不是结果值,而是类型与余数:

  a / b   → 2.5   类型 float:普通除法不丢小数
  a // b  → 2     类型 int:商的部分,余数丢弃
  a % b   → 1     类型 int:丢掉的那个余数,在这里捡回来
  关系:5 = 2 × 2 + 1,即 a = b × (a // b) + (a % b)

最后一个等式是小学除法「被除数 = 除数 × 商 + 余数」的直译——// 和 % 是同一个除法拆出来的两件战利品,理解了这个,两个符号就再也忘不掉 (这条等式是我们补的数学背景,原书未写)。

算术优先级:谁先算

多个运算挤在一个式子里时的规矩,原书从高到低列了四级10:

  ① 括号 ()        最优先——不确定就加括号,永远不亏
  ② 幂 **         其次
  ③ * / // %      再其次,同级从左到右
  ④ + -           最低,同级从左到右

书里的演示例:result = 2 + 3 * (4 - 1) 得 11(括号先 → 乘 → 加); result = (2 + 3) * 4 得 20——同一堆数,括号位置一变,答案就变11。

5. 第三组:比较(关系)运算 — 产出布尔值

六个比较运算符,每个的产出都是 True 或 False 之一12:

写法 意思 例子(x=2, y=3)
x == y 相等吗 2 == 3 → False
x != y 不等吗(!= 是「不等于」的记号) 2 != 3 → True
x > y / x < y 大 / 小 2 > 3 → False;2 < 3 → True
x >= y / x <= y 大于等于 / 小于等于 2 >= 3 → False;2 <= 3 → True

原书练习的输出是极好的记忆钉子:2 > 3 is False、2 < 3 is True 一连六行, 每个结果都跟运算符的字面意思对得上13。

判断(我们的,不是书里的): 新人最容易咬到的一颗钉是 = 和 == 的分工: x = 5 是「把 5 给 x」,x == 5 是「x 等于 5 吗」——一个是动作,一个是问题。 写成 if x = 5 直接语法报错,因为 Python 绝不允许在要布尔值的地方塞赋值。 原书把这颗钉留给了 GenAI 互动区的一行提问(「怎么避免 = 和 == 混淆」)14, 我们把它提前到这里讲——这颗钉越早拔越好。 如果错,会错在: 个别语言(如 C)里 if (x = 5) 是合法且有含义的, 所以「= 在条件里是错的」只是 Python 的规矩,不是所有语言的规矩。

6. 第四组:逻辑运算 — 把布尔值拧在一起

and、or、not 三个词,操作对象是布尔值,产出也是布尔值15。 规则一张真值表(truth table:把所有输入组合的结果列成表)说尽, 原书的 Table 4.1 我们照搬16:

a b a and b a or b not a
True True True True False
True False False True False
False True False True True
False False False False True

读法一句话:and 要求两个都真才真(一假则假);or 要求至少一个真就真 (一真则真);not 是把真假整个翻过来16。注意 and / or / not 是英文单词 而不是符号——Python 的设计哲学之一就是「代码像英语一样读」, year % 4 == 0 and year % 100 != 0 读起来几乎就是英语句子。

逻辑运算自己也有优先级:not 最高,and 其次,or 最低,括号照旧最优先17。

主线例子:判断闰年 — 四组运算全员上阵

原书练习的压轴题:闰年规则——是 4 的倍数,但逢 100 整除的年份必须同时被 400 整除。 测试数据:2000 → True,2100 → False,2024 → True,2023 → False18。

year = int(input('Enter a year: '))
leap = year % 4 == 0 and year % 100 != 0 or year % 400 == 0
print(leap)

拿 2024 走一遍(2023 的演示见原书18,这里补一个 2024):

  ① year = 2024
  ② year % 4 == 0   → 0 == 0 → True      (算术 % 先算,比较 == 后算)
  ③ year % 100 != 0 → 24 != 0 → True
  ④ True and True   → True
  ⑤ year % 400 == 0 → 2024 % 400 = 24,24 == 0 → False
  ⑥ True or False   → True
  ⑦ print 输出 True —— 2024 确实是闰年 ✓

  再拿 2100 走一遍:
  ① 2100 % 4 == 0 → True;2100 % 100 != 0 → 0 != 0 → False
  ② True and False → False;2100 % 400 == 0 → 100... 2100 % 400 = 100,== 0 → False
  ③ False or False → False —— 2100 不是闰年 ✓(这条规则正是为整百年份设的)

  图说:% 负责问「是不是倍数」,== / != 负责把答案变成 True/False,
  and/or 负责把多条规则拧成一条。四组运算各司其职,一个不缺。

注意表达式靠优先级恰好成立:% 先于 == 先于 and 先于 or17。 但原书同款式子不加括号,我们建议你加括号写: (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)—— 结果一样,但读者(三个月后的你)不用背优先级表。

判断(我们的,不是书里的): 闰年题是全书到此为止质量最高的一道练习: 它把「规则翻译成表达式」这个程序员的核心动作完整走了一遍——现实世界里 需求都是人话(「逢百必除尽四百」),代码是另一门语言,中间隔着的就是这一翻译步。 书没有点破这层,但它选的题天然在教这个。 如果错,会错在: 如果学习者只抄答案不走 2024/2100 两遍手算,这题就退化成 抄写了——价值全在翻译步,不在结果。

7. 练习走查一:十二道优先级题,先心算再验证

原书练习区列了十二个表达式,要求先自己算、再用代码验20。 这个「先心算后验证」的顺序就是学优先级的正确姿势——我们挑六道最有代表性的, 把心算过程摊开:

表达式 心算步骤 结果
2 + 3 * 4 乘先于加:2 + 12 14
(2 + 3) * 4 括号一改,先 5 * 4 20
10 + 2 / 3 除先于加:10 + 0.666… 10.666666666666666(float!)
3 ** 2 * 4 幂先于乘:9 * 4 36
12 - 3 / 2 3 / 2 = 1.5;12 - 1.5 10.5
10 / (2 + 3) 括号:10 / 5 2.0

六道题三个信息:

  1. 结果的数字类型跟着运算走:凡是 / 参与,结果必是 float(10.666…、2.0), 哪怕数学上是整数8。
  2. 第三题原书的批注露了馅:书里把 10 + 2 / 3 的心算写成「10 + 0.67 = 10.67」21, 但真实输出是 0.666…无限循环——批注是约数,输出是精确值,以输出为准。 (顺带说,0.1 + 0.2 ≠ 0.3 那种浮点怪象,是「计算机怎么存小数」的大话题, 本书不涉及,先知道「float 有精度边界」即可。)
  3. 括号是唯一的方向盘:同一堆数,括号挪一个位置,答案就从 14 变 20、从 10.5 变别的。 「不确定就先加括号」是这一章性价比最高的一句话。

8. 练习走查二:亲手验一遍真值表

逻辑练习的仪式感很强:令 x = True、y = False,把真值表全部十行 (and 四行、or 四行、not 两行)逐一打印验证22:

  True and True is True      ← and 全真才真的正面证据
  True and False is False    ← 一假则假
  False and True is False    ← 交换位置照样假
  False and False is False
  True or True is True
  True or False is True      ← 一真则真
  False or True is True
  False or False is False
  not True is False          ← not 翻面
  not False is True

十行输出与原书逐字一致22。别嫌十行多——这一遍亲手打过,第 07 章组合条件 (「成绩及格并且作业交齐或者有免考资格」)时你的脑子才不会打结。 练习区最后还有五道逻辑求值小题和闰年压轴,前面主线例子已经走透,这里不再重复。

9. 增强赋值:七个速写符号

总结表出现过、正文没讲的 += 家族,值得正式认识一分钟6:

x = 5
x += 3   # 等价于 x = x + 3,x 变成 8
x -= 2   # 等价于 x = x - 2,变成 6
x *= 4   # 变成 24
x //= 5  # 变成 4(整除后存回)

规律一句话:把运算符插在 = 前面,就是「先算再存回自己」。 它在循环里(第 08 章)会高频出现——count += 1 是「数一次」的标准写法, 现在先眼熟。

10. 操作数:一个总结表带来的词

总结表里每类运算都标了「operand(操作数)」一栏,正文没解释这个词, 补在这里:操作数就是运算符两旁被它操作的值23。a + b 里 a 和 b 是 + 的操作数;year % 4 == 0 里 % 的操作数是 year 和 4,而 == 的操作数是 year % 4 的结果和 0——一个运算的产出可以是下一个运算的操作数, 这就是「表达式」这个词的全部分量。记住「操作数」这个名字,你读任何语言的 文档都会撞见它。

11. 作者的判断与证据

  • 「四组运算」的分类是原书的组织骨架19,它对应了几乎所有命令式语言的运算全集 (分类本身是教学判断,不是语言规范——规范里没有「四组」这个说法)。
  • 真值表教学法直接来自数字逻辑课程的通行做法,书里没提来历16。
  • 总结表(Table 4.2)出现正文没讲过的东西(+= 系列增强赋值、 「operand/操作数」一词)6——表比正文宽,这是编排上的一个小毛边, 我们的 §9、§10 两节就是替这张表补的正文。

11. 边界与局限

  • 没有讲位运算。 &、|、>> 等二进制层面的运算本书完全没碰——入门书的正常取舍, 但你在别人的代码里迟早撞见,撞见时知道「这是另一类运算」即可。
  • 没有讲短路求值。 GenAI 互动区问了「short-circuit evaluation」14, 正文却没答:and 算出左边 False 就懒得算右边、or 算出左边 True 就懒得算右边。 这不只是性能优化——x != 0 and 10 / x > 2 这种写法依赖短路才不出错。 正文缺席,我们在这里补上。
  • 除零没讲。 10 / 0 会报 ZeroDivisionError。书在 GenAI 提示里问了14, 正文没有处理——「程序怎么优雅地应对错误」这个话题本书整体留空,第 07 章也不会补, 这是入门书的一个系统性缺口。
  • 优先级表只给了算术和逻辑两族,混合四种运算的完整优先级链(比如比较和逻辑 谁先谁后)要靠练习自己摸——闰年式子其实已经在考这个了。
  • 没有讲字符串的运算。 + 和 * 用在字符串上完全是另一番景象 ('ab' + 'cd' 得 'abcd','ab' * 3 得 'ababab')——「运算符对不同类型 有不同含义」是 Python 的重要特性,原书把这一面完整留给了第 05 章, 这里先预告,免得你以为 + 只会算数。
  • 「== 比不同类型」的行为没讲。 5 == '5' 得 False 而不是报错——Python 的 比较允许跨类型,只回答「不相等」。书里在 GenAI 提示里问了一句「比较不兼容类型 会怎样」14,正文没答:不会炸,只是多半得 False。

12. 可带走的

  1. = 是赋值不是等于;== 才是「相等吗」——一个动作,一个提问,写错直接报错212。
  2. x = 6 换掉的是 x 的指向,y 不受影响3。
  3. x, y = 5, 6 先算右边再按序分给左边;还能与 input 合用,一行问多个值45。
  4. / 永远得 float(10 / 2 也是 5.0);要整数商用 //(向下取整),要余数用 %8。
  5. 优先级:括号 > ** > * / // % > + -;同级从左到右;拿不准就加括号10。
  6. 六个比较运算产出 True/False;2 < 3 is True 这样的输出是最好的记忆钉; 比较允许跨类型,5 == '5' 得 False 不报错13。
  7. and 全真才真,or 有真则真,not 翻面;优先级 not > and > or;建议加括号写明意图1617。
  8. 闰年式子是四组运算的合练:year % 4 == 0 and year % 100 != 0 or year % 400 == 018。
  9. and/or 会短路:左边定了胜负,右边根本不算——有些代码靠这才安全(正文没讲,见边界节)14。
  10. += 是「加完存回自己」的速写,共七种6。
  11. 表达式就是「运算套运算」:year % 4 == 0 里,% 的产出是 == 的操作数23。
  12. 练习的规矩:先心算、后验证;批注里的约数不等于输出的精确值2021。

13. 原文地图

主题 原书章 原文位置
四组运算总览 CHAPTER 4: Operations text/13-ch04-chapter-4-operations.txt:5(搜「four main categories」)
赋值与「地址/引用」模型 同上 text/13-ch04-chapter-4-operations.txt:17(搜「denoted by the equals sign」) · text/13-ch04-chapter-4-operations.txt:36(搜「y will not change」)
多重赋值与求值顺序 同上 text/13-ch04-chapter-4-operations.txt:43(搜「assign values to multiple variables」) · text/13-ch04-chapter-4-operations.txt:100(搜「evaluated first」)
name/age 一行双问练习 同上 text/13-ch04-chapter-4-operations.txt:60(搜「int(input('What is your age」)
七个算术运算符 同上 text/13-ch04-chapter-4-operations.txt:71(搜「basic arithmetic operations」)
a=5 b=2 七连演示 同上 text/13-ch04-chapter-4-operations.txt:87(搜「print(a + b)」)
算术优先级四级 同上 text/13-ch04-chapter-4-operations.txt:97(搜「precedence of arithmetic operations」)
优先级演示例 同上 text/13-ch04-chapter-4-operations.txt:105(搜「2 + 3 * (4 - 1)」)
六个比较运算符 同上 text/13-ch04-chapter-4-operations.txt:169(搜「returns True if a is equal to b」)
x=2 y=3 六连比较输出 同上 text/13-ch04-chapter-4-operations.txt:196(搜「x = 2」)
三个逻辑运算符与真值表 同上 text/13-ch04-chapter-4-operations.txt:244(搜「three logical operations」) · text/13-ch04-chapter-4-operations.txt:251(搜「Truth table for logical operations」)
逻辑优先级 同上 text/13-ch04-chapter-4-operations.txt:298(搜「precedence of logical operations」)
闰年练习与判定式 同上 text/13-ch04-chapter-4-operations.txt:322(搜「leap year, by definition」) · text/13-ch04-chapter-4-operations.txt:330(搜「Enter a year」)
总结表(含增强赋值) 同上 text/13-ch04-chapter-4-operations.txt:338(搜「Summary of Python operations」)
GenAI 互动问题 同上 text/13-ch04-chapter-4-operations.txt:390(搜「divide by zero」) · text/13-ch04-chapter-4-operations.txt:391(搜「short-circuit」)


  1. 出处:「CHAPTER 4: Operations」第 337–375 段(text/13-ch04-chapter-4-operations.txt:338,搜「Summary of Python operations」)。四组运算的分类依据原书第 5–10 段(text/13-ch04-chapter-4-operations.txt:5,搜「four main categories of operations」)。 ↩

  2. 出处:「CHAPTER 4: Operations」第 17–18 段(text/13-ch04-chapter-4-operations.txt:17,搜「denoted by the equals sign」)。原文:「The assignment operation in Python is denoted by the equals sign (=).」 ↩↩

  3. 出处:「CHAPTER 4: Operations」第 27–41 段(text/13-ch04-chapter-4-operations.txt:29,搜「y = x」;:36,搜「y will not change」;:41,搜「still output 5」)。「不是把 5 改成 6」的表述依据原文「When we assign a new value to x, it will point to a new location in memory」。 ↩↩

  4. 出处:「CHAPTER 4: Operations」第 43–54 段(text/13-ch04-chapter-4-operations.txt:46,搜「x, y = 5, 6」;:52,搜「right-hand side」)。执行顺序逐字依据原文。 ↩↩

  5. 出处:「CHAPTER 4: Operations」第 56–65 段(text/13-ch04-chapter-4-operations.txt:60,搜「What is your age」;:63,搜「What is your name: Neo」)。输入 Neo / 18 的输出 Neo is 18 years old. 见原文。 ↩↩

  6. 出处:「CHAPTER 4: Operations」第 365–375 段(text/13-ch04-chapter-4-operations.txt:365,搜「Assign values or modify and assign」)。增强赋值七种只在总结表出现,正文未展开——这是我们对原书编排的观察。 ↩↩↩↩↩

  7. 出处:「CHAPTER 4: Operations」第 71–81 段(text/13-ch04-chapter-4-operations.txt:71,搜「basic arithmetic operations supported」)。七个运算符的定义逐条依据原文。 ↩

  8. 出处:「CHAPTER 4: Operations」第 84–93 段(text/13-ch04-chapter-4-operations.txt:87,搜「print(a + b)」)。5 / 2 → 2.5、5 // 2 → 2、5 % 2 → 1 等输出逐字依据原文演示。「/ 永远交出 float」依据原文第 75 段「returns a float as the result」。 ↩↩↩↩

  9. 补充(不在书里,来自通用知识):// 对负数向下取整(-5 // 2 == -3);原书整除说明只说「returns the largest whole number result」(第 77–78 段),未涉及负数。 ↩

  10. 出处:「CHAPTER 4: Operations」第 97–104 段(text/13-ch04-chapter-4-operations.txt:97,搜「precedence of arithmetic operations」)。四级优先级逐字依据原文。 ↩↩

  11. 出处:「CHAPTER 4: Operations」第 105–126 段(text/13-ch04-chapter-4-operations.txt:105,搜「2 + 3 * (4 - 1)」;:108,搜「(2 + 3) * 4」)。11 与 20 的对照见原文输出。 ↩

  12. 出处:「CHAPTER 4: Operations」第 164–182 段(text/13-ch04-chapter-4-operations.txt:169,搜「returns True if a is equal to b」)。六个比较运算符的定义逐条依据原文。 ↩↩

  13. 出处:「CHAPTER 4: Operations」第 184–210 段(text/13-ch04-chapter-4-operations.txt:205,搜「2 > 3 is False」)。六行输出见原文。 ↩↩

  14. 出处:「CHAPTER 4: Operations」第 389–396 段(text/13-ch04-chapter-4-operations.txt:392,搜「confusion between = and ==」)。「短路求值」「除零」两问由 GenAI 互动区提出而正文未答,我们的补充写在 §8 边界与局限。 ↩↩↩↩↩

  15. 出处:「CHAPTER 4: Operations」第 240–247 段(text/13-ch04-chapter-4-operations.txt:241,搜「only two values」;:244,搜「three logical operations」)。 ↩

  16. 出处:「CHAPTER 4: Operations」第 248–256 段(text/13-ch04-chapter-4-operations.txt:251,搜「Truth table for logical operations」)。真值表结构与数值逐格依据原文 Table 4.1;「一假则假/一真则真」的口诀是我们的概括。 ↩↩↩↩

  17. 出处:「CHAPTER 4: Operations」第 298–302 段(text/13-ch04-chapter-4-operations.txt:298,搜「precedence of logical operations」)。() > not > and > or 逐字依据原文。 ↩↩↩

  18. 出处:「CHAPTER 4: Operations」第 322–335 段(text/13-ch04-chapter-4-operations.txt:322,搜「leap year, by definition」;:325,搜「input: 2000: True」;:331,搜「year % 4 == 0 and year % 100」)。四个测试年及判定式逐字依据原文;文中 2024 的手算推演是我们补的验算。 ↩↩↩

  19. 出处:「CHAPTER 4: Operations」第 5–10 段(text/13-ch04-chapter-4-operations.txt:5,搜「four main categories of operations」)。四类及其一句话定位逐字依据原文。 ↩

  20. 出处:「CHAPTER 4: Operations」第 131–162 段(text/13-ch04-chapter-4-operations.txt:132,搜「Evaluate following arithmatic operations」)。十二道题及「先估后验」的要求逐字依据原文。 ↩↩

  21. 出处:「CHAPTER 4: Operations」第 149 段(text/13-ch04-chapter-4-operations.txt:149,搜「10 + 0.67」)。原书批注把 2/3 约成 0.67,而第 159 行的实际输出为 10.666666666666666——「批注是约数、输出是精确值」的出入即出自这两处。 ↩↩

  22. 出处:「CHAPTER 4: Operations」第 258–296 段(text/13-ch04-chapter-4-operations.txt:274,搜「x = True」;:287,搜「True and True is True」)。十行验证输出逐字依据原文。 ↩↩

  23. 出处:「CHAPTER 4: Operations」第 340–364 段(text/13-ch04-chapter-4-operations.txt:340,搜「Operation Operator」)。「operand/操作数」一词出自原书总结表的表头。 ↩↩