数据结构、函数契约、模块、虚拟环境与事实边界
Python 工程最小心智模型
能闭卷解释常用容器和可变性,独立写带类型、异常和测试的最小数据模型。
ONE MENTAL MODEL
本周先抓住这一幅图先把数据的含义和不变量写成契约,再让函数改变状态。Python 的灵活性不是免除设计,而是要求你主动划出边界:什么可以变、谁负责校验、错误怎样被调用者看见。
00 · 学习边界
把有限记忆留给高频判断
必须长期记住 · 5
- list 表达有序可变集合,tuple 常表达固定结构或不可重新赋值的序列,dict 用键表达命名关系。
- 赋值通常复制引用而非对象;共享可变对象会让一个位置的修改影响另一个位置。
- 类型提示主要服务静态检查和阅读,不会自动完成运行时校验。
- 函数契约至少包含输入、输出、不变量、边界和失败语义。
- 项目事实必须区分已实现、已运行、仅设计和明确未验证。
允许按需查表
- typing 模块所有泛型写法
- venv 在不同操作系统的激活命令
- dataclass 的全部可选参数
判断标准:能说明它解决什么、何时用、会怎样失败;精确参数不占长期记忆。
核心章节
按语义选择容器,而不是背性能口号
容器首先传达领域含义。读数序列需要顺序和追加,适合 list;不可改变的坐标对可以用 tuple;按传感器 ID 查配置需要 dict。面试官更关心你为何选择,而不是一句‘tuple 更快’。
可变性意味着对象内容能在身份不变时改变。两个变量指向同一 list 时,任何一方 append 都可见。函数默认参数在定义时求值,因此把 [] 放在默认参数里会跨调用共享。
你需要带走的判断
- 赋值与复制不同
- 浅拷贝仍共享嵌套对象
- 作为 dict key 的对象需要稳定哈希语义
a = []; b = a; b.append(1) 后 a 也是 [1]。修复默认参数时使用 None,再在函数内部新建 list。
只背 list 可变、tuple 不可变,却不能预测共享引用代码的实际结果。
对应 D1 的闭卷容器解释和可变对象追问。
核心章节
函数、类型与异常共同组成契约
一个可靠函数不只处理 happy path。以 summarize_readings 为例,空输入是否返回空结果、None 还是抛 ValueError 必须明确;选择取决于调用者能否把空集合视为合法业务状态。
类型提示表达设计意图,运行时边界仍需显式校验。外部 JSON、数据库行和模型输出都是不可信输入;先解析成边界模型,再进入领域函数。不要用 Any 把未知问题藏起来。
你需要带走的判断
- 错误信息应指出字段和违反的不变量
- 返回 dict 适合命名字段,值对象适合更强约束
- 测试要覆盖正常、最小、空和非法输入
def summarize(values: list[float]) -> Summary: 若 not values,明确 raise ValueError('values must not be empty')。
为了让函数‘不报错’而吞异常或返回含糊的空值。
对应 D1–D5 的汇总函数、Schema、模型与三个单元测试。
核心章节
模块与环境决定代码能否复现
虚拟环境隔离的是项目所使用的解释器环境和第三方包版本。它不自动锁定依赖,所以还需要可重复的依赖声明。python -m pytest 让 pytest 由当前 Python 解释器加载,能减少命令来自另一环境的混乱。
包结构、导入路径和执行入口要一致。把业务逻辑放在可导入模块,把启动代码放在明确入口;测试从公共接口导入,不靠修改 sys.path。
你需要带走的判断
- 知道当前 python 来自哪里
- 从空目录能重建环境
- 运行命令和测试结果都属于证据
只在 IDE 中能运行,换目录或换机器就出现导入错误。
对应 D2 的环境复现和 D4 的项目骨架。
R · 主动回忆
先合上教材,再回答
显示 5 道闭卷自测题先用纸口述,再展开核对问题
- 为什么两个变量的 list 会互相污染?画引用图。
- 类型提示保证了什么,不保证什么?
- 空列表求平均值应怎样定义失败语义?
- 为什么 python -m pytest 常比直接 pytest 更容易复现?
- 你当前项目有哪些事实仍未被验证?
本周最小实验
关掉教材,从空目录创建环境,写三个领域模型、一个汇总函数和三个 pytest;删除后再重写一次,并记录第一次失败的原因。
✓ · 教材完成
只有能复现,才算学过
↗ · 一手资料