三个案例 — 把前五章缝在一起
三个案例 — 把前五章缝在一起
这一章没有新概念,只有三道应用题。 前五章学的是零件,这一章把零件 装成三台小机器:超市收银、聚餐分账、复利计算器。读完你会形成一个重要认识: 入门阶段的程序,长得都很像。
1. 这一章在全书链条里的位置
这是第一部分的收官章。原书在前言里说过,案例的作用是「把小块知识组合起来, 展示怎么用它们解决真实问题」1——如果说第 02–05 章是体检的每一项指标, 这一章就是综合体检。它同时是第二部分(流程控制)的入口:file 末尾的部分导读 预告了接下来的主题——分支、循环、函数2。
2. 三个案例共用的骨架
把三个程序的代码并排摆开,会发现它们是同一个模子:
① 问数字 xxx = float(input('...')) 或 int(input('...'))
——input 给字符串,转换器拆掉类型墙(第 02/03 章)
② 算 一行算式,把业务规则翻译成运算(第 04 章)
③ 打印 print(f'... ${结果:.2f}')
——f-string 嵌值,:.2f 把金额钉在两位小数(第 05 章)
图说:三个案例的差异全部集中在第 ② 步的那行算式上。这一章真正的教学点就一个:业务规则怎么翻译成算式。下面逐台机器走一遍, 每一步都带原书给出的具体数字。
3. 案例一:收银找零(主线例子)
规则:顾客一单只买一种商品,不限量;税率 6.25%;先算含税总额,再问顾客付了多少, 找零3。
price = float(input('What is the price per unit of the product? '))
quantity = int(input('What is the quantity of the product? '))
total = price * quantity * (1 + 0.0625)
print(f'The total amount of this order with tax is ${total:.2f}')
paid = float(input('What is the amount of bill paid? '))
change = paid - total
print(f'The change is ${change:.2f}')拿原书的演示输入走一遍(单价 25.99,数量 12,付款 350):
① price = 25.99 (字符串 '25.99' → float 转换)
② quantity = 12 (字符串 '12' → int 转换)
③ 小计 = 25.99 × 12 = 311.88
④ 税 = 311.88 × 0.0625 = 19.4925
⑤ total = 311.88 × 1.0625 = 331.3725 → 显示 $331.37(:.2f 四舍五入)
⑥ paid = 350
⑦ change = 350 - 331.3725 = 18.6275 → 显示 $18.63
图说:算式 (1 + 0.0625) 是「含税价 = 原价 × 1.0625」的直译;
显示值四舍五入、内部值不四舍五入——change 用的是 331.3725 不是 331.37。两个细节值得停一秒:其一,1 + 0.0625 这种写法读业务规则的人一眼能认出
「加六个多点的税」;其二,第 ⑤⑦ 步的显示是 331.37 / 18.63,但第 ⑦ 步减法
用的是内部精确值——格式化只改显示,不改数值4。
4. 案例二:聚餐分账加小费
规则:饭前总额,税率 6.25%,小费 18%,人头数均摊5。
total = float(input('What is the total amount of the meal before tax? '))
num = int(input('How many people to split the tips? '))
tax = 0.0625
tip = 0.18
total_due = total * (1 + tax + tip)
each_due = total_due / num
print(f'Total due is ${total_due:.2f}. Each due is ${each_due:.2f}')原书输入:饭前 124 美元,5 人。走一遍:124 × 1.2425 = 154.07,
154.07 / 5 = 30.814 → 显示 Total due is $154.07. Each due is $30.816。
这一版比案例一多一个进步:税率和小费被起成了名字(tax = 0.0625),
而不是像案例一那样把 0.0625 裸写在算式里。名字化之后,算式
total * (1 + tax + tip) 读出来就是业务规则本身。这就是第 03 章
「名字要有描述性」惯例的实战回报7。
5. 案例三:复利计算器
规则:本金、年数、年利率(0.03 表示 3%),算到期总额8。
saving = float(input('What is the amount of saving right now? '))
years = int(input('What is the number of years? '))
rate = float(input('What is the interest rate per year? '))
total = saving * (1 + rate) ** years
print(f'The total amount after these years is: ${total:.2f}')原书输入:本金 100000,10 年,年利率 0.05。算式是复利公式
「本息 = 本金 × (1 + 利率)^年数」的直译,** 运算符第一次挑大梁(第 04 章的
5 ** 2 在这里变成了 1.05 ** 10)。结果 162889.46——十万本金以 5% 复利
滚十年,变成了约十六万三9。
① 1.05 ** 10 = 1.6288946… (幂运算:十年增长因子)
② 100000 × 1.6288946… = 162889.46
图说:(1 + rate) ** years 一个式子装下了整个复利公式。6. 作者的判断与证据
- 案例选择是精心校准过的:收银(加减乘)、分账(除)、复利(幂)——三个案例 恰好把第 04 章的算术运算符按难度递进全部用上,且都是「算钱」,对初学者 没有领域门槛。
- 每个案例开头都明确标注输入类型要求(「it should be a float」)3, 这是把「input 返回字符串、必须转换」这条铁律制度化——案例不假设你已经 内化它,而是每次都示范。
- 本章开头的免责声明很重要:「此刻先假设用户会乖乖按说明输入」10。 也就是不处理乱输入(字母当数字、负数数量)——这是诚实的教学取舍: 输入校验要等流程控制(第 07 章分支)才能讲,先把主干立起来。
7. 边界与局限
- 没有校验,没有错误处理。 乱输入会 ValueError 崩掉;付款小于总额会 输出负数找零也不报警。书的立场是「先假设用户配合」,真正的防御要等第 07 章 之后的工具。
- 金额用 float 算,有精度暗坑。 0.0625、18.6275 这类小数在二进制里
存不精确,
:.2f的四舍五入只是遮羞。真实金融系统用decimal模块—— 本书没提,入门阶段接受 float 的近似即可(第 05 章边界节预告过)。 - 三个案例都是「一问一答一输出」的脚本形态,没有循环、没有分支—— 第二部分学完,同样的题目可以重写成「反复结账直到收工」的样子,那才是 真正的收银系统。
8. 可带走的
- 入门程序的统一骨架:问(input+转换)→ 算(一行算式)→ 秀(f-string +
:.2f)。 - 业务规则翻译成算式,是本阶段的核心手艺(含税 × 1.0625、复利 × (1+r)^n)38。
- 常量起名字(tax、tip),算式就能读成人话7。
:.2f只改显示不改数值;内部计算用精确值4。- 收银案例里「付款→找零」两步,是最小版本的「状态接着上一步走」。
- 学完第 07、08 章,值得回到这三个案例做升级版:加输入校验、循环结账。
9. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 案例的定位与输入假设 | CHAPTER 6: Case Studies of Python Fundamentals | text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:9(搜「test your understanding」) · text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:13(搜「assume users will follow instructions」) |
| 收银规则六条 | 同上 | text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:24(搜「sales tax of 6.25%」) |
| 收银代码与演示数字 | 同上 | text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:31(搜「price per unit」) · text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:51(搜「25.99」) |
| 分账规则与代码 | 同上 | text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:60(搜「total amount of meal before tax」) · text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:83(搜「124」) |
| 复利规则与代码 | 同上 | text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:90(搜「amount saved right now」) · text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:110(搜「100000」) |
| 第二部分导读(分支/循环/函数预告) | 同上 | text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:114(搜「Flow Control and Functions」) |
Footnotes
-
出处:「Preface」第 53–54 段(
text/08-fm-preface.txt:53,搜「Case studies combine」)。原文:「Case studies combine all the small ideas to show how you can use them to solve real-world problems.」 ↩ -
出处:「CHAPTER 6: Case Studies of Python Fundamentals」第 114–133 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:114,搜「Flow Control and Functions」)。部分导读预告的分支、循环、函数主题,即第 07–10 章。 ↩ -
出处:「CHAPTER 6: Case Studies of Python Fundamentals」第 19–27 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:19,搜「check-out system」;:24,搜「sales tax of 6.25%」)。六条规则逐字依据原文。 ↩ ↩2 ↩3 -
「格式化只改显示不改数值」是对
:.2f机制的通用知识补充;演示中的输入输出(331.37、18.63)见原文第 51–55 段(text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:51,搜「25.99」)。手算分解(311.88、19.4925、18.6275)是我们依据原书算式补的验算步骤。 ↩ ↩2 -
出处:「CHAPTER 6: Case Studies of Python Fundamentals」第 59–65 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:63,搜「tip at 18%」)。规则逐字依据原文。 ↩ -
出处:「CHAPTER 6: Case Studies of Python Fundamentals」第 83–85 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:83,搜「total amount of the meal before tax? 124」)。输入 124 / 5 人及输出 $154.07 / $30.81 逐字依据原文。 ↩ -
「tax/tip 名字化的进步」是我们的观察;代码本身见原文第 72–73 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:72,搜「Set the tax rate」)。 ↩ ↩2 -
出处:「CHAPTER 6: Case Studies of Python Fundamentals」第 89–94 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:92,搜「interest rate (it should be」))。规则逐字依据原文。 ↩ ↩2 -
出处:「CHAPTER 6: Case Studies of Python Fundamentals」第 110–113 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:110,搜「100000」)。输入 100000 / 10 年 / 0.05 及输出 162889.46 逐字依据原文。 ↩ -
出处:「CHAPTER 6: Case Studies of Python Fundamentals」第 13–14 段(
text/15-ch06-chapter-6-case-studies-of-python-fundamentals.txt:13,搜「assume users will follow instructions」)。原文:「we can assume users will follow instructions carefully」。 ↩