跳转至

结业测验(10/7,闭卷)

第一、二部分 60 分钟笔答(20 题,每题 1 分);第三部分 30 分钟限时编码(10 分)。总分 30,≥24 通过。答案与参考实现见 exercises/solutions/final/

规则:不开 AI;第三部分可以开 REPL 与 pytest,但不能翻本仓库的答案目录。

第一部分:概念与预测(12 题)

  1. 生成器与列表推导式在"内存"与"可重复遍历"上各有什么区别?写出一行代码证明生成器只能遍历一次。
  2. 闭包"晚绑定"是什么?[lambda: i for i in range(3)] 的三个函数都返回什么?两种修法。
  3. @functools.wraps 保住了哪些属性?没有它,inspect.signature 拿到的会是谁的签名?
  4. __eq____hash__ 的关系;@dataclass(frozen=True) 为什么天然可哈希?
  5. ProtocolABC 各一句话;learn-agent 里工具接口更适合哪一个,为什么?
  6. try/except/else/finally 四段各在什么时候执行?finallyreturn 会发生什么(3.14 会给你什么警告)?
  7. raise NewError(...) from e 与不写 from e 的区别体现在哪里?什么时候用 from None
  8. Pydantic:Optional[int]int | None = NoneField(default_factory=list) 三者在"必填/可省略/默认值共享"上的区别。
  9. model_dump()model_dump(mode="json") 的区别;model_json_schema()required 是怎么决定的?
  10. 一段 async def 端点里调用了 time.sleep(1),5 个并发请求总耗时约多少?三种修法。
  11. asyncio.gatherasyncio.TaskGroup 在"一个任务失败"时的行为差异;ExceptionGroup 怎么拆。
  12. httpx.Client 应该建几次?不设超时的后果?哪些请求可以自动重试、哪些不可以?

第二部分:工程判断(8 题)

  1. src 布局解决了什么问题?python src/kb/cli.py 为什么会 ModuleNotFoundError
  2. pyproject.toml[project.dependencies][dependency-groups].dev 的区别;uv.lock 的作用。
  3. logging:库模块里该写什么、不该写什么;logger.error(e)logger.exception(e) 的差别。
  4. 正则 re.match / re.search / re.fullmatch 的区别;.*.*? 的区别;什么时候不该用正则。
  5. SQLite:为什么必须参数化查询?with conn: 做了什么?为什么建表语句要 IF NOT EXISTS
  6. pytest:patch 为什么要"打到使用处"?fixture 的 yield 之后的代码何时执行?覆盖率 100% 能说明什么、不能说明什么?
  7. 分层架构:services/ 为什么不能 import fastapi?领域异常如何变成 HTTP 状态码?这样做对 agent 项目有什么直接好处?
  8. 安全五条:列出你在 kb/aggregator 审查中真正修掉的三处,以及一条你判断"不需要修"的理由。

第三部分:限时编码(30 分钟,10 分)

在一个新目录里实现模块 bookshelf.py 和测试 test_bookshelf.py,要求:

领域 - BookshelfError(Exception) 基类;子类 BookNotFoundErrorDuplicateIsbnError - @dataclass(frozen=True) Book(id: int | None, isbn: str, title: str, tags: tuple[str, ...], added_at: datetime)

输入校验(Pydantic) - BookInisbn 必须是 13 位数字(pattern=r"^\d{13}$");title 去首尾空白后 1–200 字;tags 默认空、最多 5 个、自动小写去重;未知字段拒绝(extra="forbid"

仓储 - BookRepository(Protocol)add(book) -> Book(分配 id)、get(id) -> Book | Nonefind_by_isbn(isbn) -> Book | Nonelist() -> list[Book] - 至少一个实现:InMemoryBookRepositorySqliteBookRepository 加分)

服务 - Bookshelf(repo): - add(data: dict) -> Book:用 BookIn 校验(失败让 ValidationError 抛出),ISBN 已存在抛 DuplicateIsbnErroradded_at 用 UTC 当前时间 - get(id) -> Book:不存在抛 BookNotFoundError - by_tag(tag) -> list[Book]:不区分大小写

测试(≥3 个,pytest) - 正常添加:id 为 1、标题被 strip、标签小写去重 - 非法输入:至少一种(ISBN 位数错 / 标题空 / 标签超 5 / 多余字段)抛 ValidationError - 重复 ISBN 抛 DuplicateIsbnError;不存在的 id 抛 BookNotFoundError

评分(10 分):领域与异常 2|Pydantic 校验 3|Protocol + 实现 2|服务逻辑 1|测试 2。ruff check 有警告扣 1,无类型注解扣 1。