学径XUEJING · 个人学习平台通知设置

课程库 AI 主线 Python 进阶语法 › 第 7

单元测验 + 重构挑战:把一段烂代码改优雅

里程碑45 分钟

本课导读

U1.1 的关卡到了,分两关:第一关综合测验 10 题,覆盖本单元全部六课;第二关重构挑战——一段能跑但没法看的真实风格烂代码,用这六课的全部功夫把它改优雅。通过标准:测验全对 + 重构后运行结果与原版一致。预计 45 分钟。

赛前热身:本单元的知识地图

一句话回顾
1. 列表进阶切片含头不含尾;sorted 复印 .sort 原地;推导式 = 质检+加工流水线
2. 字典与集合进阶.get 兜底;嵌套一层剥一个方括号(JSON 的形状);set 去重 + 交并差
3. 函数进阶默认参数必填在前;调用时关键字点名;return 多值 → 解包
4. 作用域与模块函数内赋值是局部变量;参数进 return 出;import 三姿势 + 标准库
5. 错误与异常处理traceback 从最后一行往上读;except 写明类型;预防优先于抢救
6. 代码风格蛇形命名见名知意;注释说为什么;PEP8 五条最小集

第一关:综合测验

随堂测验0 / 10 题正确

1. nums = [5, 2, 8, 1, 9],一行取出“从大到小的前 2 名”的写法是?

2. [len(w) for w in ["ai", "data", "ml"] if len(w) > 2] 的结果是?

3. resp = {"user": {"tags": ["vip", "new"]}},取出 "new" 的写法是?

4. 想统计一个列表里有多少个不同的值,最顺手的写法是?

5. def notify(msg, urgent=False): 定义后,哪个调用会报错?

6. def stats(nums): return max(nums), min(nums) —— 正确接住两个结果的写法是?

7. total = 0,函数体里写 total = total + n 想累加全局的 total,实际会发生什么?

8. import pandas as pd 之后,正确的用法是?

9. int(raw) 转换用户输入,要接住“输入了文字”的意外,except 后面写哪种类型?

10. 下面哪个函数头最符合本单元的风格标准?

第二关:重构挑战

下面这段代码出自"三个月前的你"之手:功能完全正常——统计各部门报销总额、找出超预算的部门。但它集齐了本单元批判过的所有毛病。

你的任务:逻辑和输出保持一致,把它改到能见人。改完运行,输出应与原版一字不差。

Python

改造清单(对照六课逐项检查):

  • 函数名、变量名全部换成见名知意的蛇形英文(第 6 课)
  • 2000 这个魔法数字提成常量或带名字的默认参数(第 3、6 课)
  • 累加部分用 .get(键, 0) 简化 if/else 四行(第 2 课)
  • 找超标部门那段改成列表推导式(第 1 课)
  • 给函数补一行 docstring(第 6 课)
  • 运算符、逗号周围的空格补齐;if ...: d.append(k) 这种挤一行的拆开(第 6 课)
💡 提示(卡住了再看)

先只做"改名"这一步——名字换好,代码的意图就浮出来了,其余每项都是局部小手术。累加那四行的 .get 写法:totals[dept] = totals.get(dept, 0) + amount

✅ 参考实现(先自己改完再对照)
BUDGET_LINE = 2000   # 部门报销预警线(元)


def summarize_expenses(records, budget_line=BUDGET_LINE):
    """汇总各部门报销总额,返回 (总额字典, 超预算部门列表)"""
    totals = {}
    for dept, amount in records:
        totals[dept] = totals.get(dept, 0) + amount
    over_budget = [dept for dept, total in totals.items() if total > budget_line]
    return totals, over_budget


expenses = [("设计", 1200), ("运营", 800), ("设计", 2300), ("行政", 450), ("运营", 1900)]
totals, over_budget = summarize_expenses(expenses)
print(totals)
print(over_budget)

对照要点:for dept, amount in records 直接解包元组(第 3 课);.get(dept, 0) 三行变一行(第 2 课);超标筛选是带条件的推导式,而且用 .items() 同时拿键值(第 1、2 课)。如果你的版本名字不同但同样清晰——完全没问题,命名没有唯一答案,清晰才是标准。

提示

彩蛋练法:把你重构后的代码发给 AI,让它"按 PEP8 和可读性最佳实践点评"——看看 AI 还能挑出什么。这个动作(写 → 重构 → 请人审)就是真实工程师的成长循环,从今天起它属于你了。

通关小结

走到这里,你的 Python 已经从"会写"升级到"写得像话":

  • 数据侧:切片/排序/推导式 + 嵌套结构 + 集合——一批数据的取、排、洗、去重都有了顺手兵器
  • 函数侧:默认参数、关键字调用、多值返回——能写出别人(和 AI)乐意用的接口
  • 工程侧:作用域心智、import 百宝箱、异常气囊、风格品味——代码开始有"工程"的样子

下个单元换个视角看世界:面向对象初步——为什么字典装数据装到一定程度就不够用了?类(class)登场。

划选正文任意文字可高亮、批注或加入复习卡

讨论

载入中…