← 编程起步:做一个学习记录小助手

第 03 课:把三条记录汇总成一个结果

学习目标:读写列表中的字典,跟踪循环中的累计值,解释空列表的结果。
前置:第 02 课的变量、整数和判断。预计 55 分钟。
本课交付:一张循环追踪表和增加第 4 条记录后的输出。

本课主线:记录增加,算法不跟着重写

一天可能学习 Python 25 分钟、阅读 15 分钟,又学 Python 20 分钟。如果定义 minutes1、minutes2、minutes3,第 4 次学习就得再修改程序结构。

用列表保存“有顺序的一组记录”,每条记录再用字典说明各个值的含义。之后循环处理每条记录,无论有 3 条还是 30 条,规则相同。

先认识数据形状

records = [
    {"subject": "Python", "minutes": 25},
    {"subject": "阅读", "minutes": 15},
    {"subject": "Python", "minutes": 20},
]

外层 [] 是列表,里面有三个元素,用逗号隔开。内层 {} 是字典,"subject" 和 "minutes" 是键,后面是对应的值。

records[0] 取第一个元素,Python 的索引从 0 开始;records[0]["minutes"] 再从这个字典取分钟数,得到 25。索引回答“第几个”,字典键回答“哪个字段”。

运行与预期输出

运行 py -3 versions/03_records.py。数据后面的处理代码是:

total = 0
for record in records:
    total = total + record["minutes"]
    print(f"加上 {record['minutes']},累计 {total}")

print(f"记录数:{len(records)}")
print(f"总分钟:{total}")

预期:

加上 25,累计 25
加上 15,累计 40
加上 20,累计 60
记录数:3
总分钟:60

for record in records 每轮让名字 record 指向下一条字典。len(records) 返回元素数量,并不把每条记录的字段也算进去。

手工走一遍循环

轮次当前 minutes执行前 total执行后 total
第 1 轮25025
第 2 轮152540
第 3 轮204060

total = total + ... 先计算右侧,再把新结果赋回左侧。它不是数学等式,而是“用旧值计算新值”。

初始化 total = 0 必须在循环外。如果把它缩进循环,每轮都从 0 开始,最后只剩最后一条的 20。这个错误用上表就能解释,无需猜测。

添加记录与空数据

在循环之前加:

records.append({"subject": "英语", "minutes": 10})

append 把一个元素加到列表末尾,之后输出应为 4 条、70 分钟。不是 records = records.append(...):这个方法直接修改列表,返回值是 None。

再临时把 records 改成 [],输出应是 0 条、0 分钟。循环一次也不执行,total 保留初值。这也是为什么初始化要在循环外。

常见错误与排错

现象可能原因检查方法
KeyError: 'minute'键名与数据不一致打印当前 record 的全部内容
结果只有 20每轮把 total 归零看初始化的缩进位置
records 变成 None接收了 append 的返回值直接调用 append,不重新赋值
IndexError请求了不存在的位置三条记录的索引只有 0、1、2

动手练习与验收

在本课代码里增加一个 long_count,统计时长至少 20 分钟的记录数量。先用原始三条记录,预期是 2;再加入 10 分钟英语记录,预期仍然是 2。

提示:在循环外初始化计数器;在循环内检查当前记录;满足条件才加 1。请先写自己的实现,再看解释。

看答案

条件应为 record["minutes"] >= 20;满足时更新 long_count = long_count + 1,等于 20 的记录也必须计入。

验收同时保留三项:原始数据 3/60、增加一条后 4/70、空列表 0/0;解释为什么列表长度和 long_count 不总是相等。

下一步

如果另一个地方也要算总分钟数,复制循环会让修改变得重复。下一课将这段规则变成可调用的函数。