关于 ac-python
ac-python 是面向 Python 3.14 项目的编码技能,供开发者编写、审查和测试 Python 代码。它汇集风格、类型、设计与测试规范,并为常见开发任务提供参考文件。
主要功能
- 01Python 3.14 指南及 Python 3.13 说明
- 02风格、类型和设计规范
- 03uv、ruff、mypy/ty 与 pytest 指南
- 04面向编码和测试任务的参考文件
- 05集成测试优先原则
适用场景
- 01编写 Python 命令行工具或服务
- 02审查 Python 代码和数据模型
- 03配置测试与项目工具
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ souliane/ skills --skill ac-python安装后在 Claude Code 中输入/ac-python确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/oop-and-design.mdstyle-and-typing.mdtesting-and-tooling.md详细介绍
Python 圣经(Python 3.14)
目标版本: Python 3.14 · 上一版本: Python 3.13(末尾章节)· 工具链: uv · ruff · mypy/ty · prek · pytest
版本策略
本技能仅记录一个 Python 版本系列:当前版本。更新时请保持这一点。
- 主路径 = 当前特性版本。 目前是 Python 3.14。Python 3.15 发布时,在同一次编辑中将主路径切换到该版本。
- 未标注的正文表示当前版本系列,且不存在标记形式。 Python 仅在特性版本中发布新功能,而主路径始终是当前特性版本,因此其中的内容不可能晚于该版本,也无需版本后缀来限定。(这正是同系列技能
ac-django的策略有所不同之处:Django 会在一个版本系列内添加功能,因此需要版本标记;Python 则不需要。)不要在主路径中写“在 Python 3.X+ 上……”或“如果你使用的是 3.13”——本规则旨在杜绝主路径中的条件语句。 - 旧版本系列各自在
SKILL.md末尾添加一个章节,除此之外不出现在其他任何位置——参考文件仅涵盖当前版本系列,不添加各自的末尾章节。目前该章节为## Previous line: Python 3.13。其中列出该版本的读者所需了解的差异:缺少哪些内容、应改用什么,以及升级时应做哪些改动。 - 刷新时的研究顺序。 首先查看
https://docs.python.org/3/whatsnew/和库参考文档,然后查看“权威来源”中已引用的资料。博客和新闻简报放在最后,简要查阅文档未涵盖的内容。 - 轮换。 每年 10 月会发布一个新版本系列:以该版本为基准更新未标注的正文,将末尾章节替换为即将淘汰的版本系列,并删除过时标记。
权威来源
- Python 文档:https://docs.python.org/3/
- Ruff 文档:https://docs.astral.sh/ruff/
- uv 文档:https://docs.astral.sh/uv/
- mypy 文档:https://mypy.readthedocs.io/
- pytest 文档:https://docs.pytest.org/
- Typer(命令行):https://typer.tiangolo.com/
参考文件(按需加载)
| 文件 | 涵盖内容 | 加载时机 |
|---|---|---|
references/style-and-typing.md | 风格、Pythonic 惯用法、类型注解、可读性规则 | 编写或审查任何 Python 代码时 |
references/oop-and-design.md | OOP 模式、数据模型、工厂、属性、设计原则 | 设计类、数据模型或模块结构时 |
references/testing-and-tooling.md | 测试模式、pytest 配置、工具链(uv/ruff/mypy/prek)、质量门禁 | 编写测试、搭建项目或配置 CI 时 |
依赖项
独立技能。不依赖其他技能。
与 ac-django 一起使用时,可提供通用 Python 指南,补充 Django 专用模式。
触发条件 QA(发布门禁)
发布技能变更前,使用示例提示词验证触发行为:
- 应触发:
- “编写一个处理 CSV 文件的命令行脚本。”
- “审查这个 Python 类的设计问题。”
- “为这个 Python 微服务配置测试。”
- 不应触发:
- “添加一个 Django 模型字段和迁移。”
- “为一个工单设置 git worktrees。”
- “实现项目交付工作流。”
如果触发不足或触发过度,请在发布前收紧 description 中的提示线索。
示例:添加新的数据模型
用户说:“添加一个带验证功能的 LoanApplication 数据模型”
- 加载
references/oop-and-design.md,了解数据模型模式 - 加载
references/style-and-typing.md,了解类型标注惯例 - 使用 dataclass;如果项目已在使用 attrs/pydantic,也可使用它们
- 添加完整的类型标注,并对派生属性使用
@cached_property - 如测试需要,工厂函数命名为
build_loan_application(...) - 在
tests/中按模块路径镜像创建测试文件
首要指令
Pythonic 优先
- 优先采用符合 Python 惯用风格的方案,而不是通用方案。
- 在能让意图更清晰时,使用列表推导式、海象运算符(
:=)、itertools和operator。 - 避免使用只用一次的中间变量。
- 使用插值值构造 SQL、HTML、Shell 命令或模板时,优先使用 t 字符串(
t"...",PEP 750),而不是 f 字符串。t 字符串的求值结果是string.templatelib.Template,而非str:静态文本和每个Interpolation都保持可分离,因此处理函数可以针对目标语法转义每个插值值。安全性取决于该函数——标准库不提供此类函数,因此请使用库提供的函数,或自行编写。将Template传给需要str的地方会报错,而不是自动转义。 - 对于 zstd,请使用标准库
compression.zstd,而不是第三方zstandard包。compression.lzma、compression.bz2、compression.gzip和compression.zlib也是这些模块的首选导入名称;原有名称仍可使用,且未弃用。tarfile、zipfile和shutil可以读写 zstd 归档。 - 当没有
as子句时,多类型except不要使用括号(PEP 758):except TimeoutError, ConnectionRefusedError:。使用as时仍必须加括号。 - 绝不要在
finally块中执行return、break或continue——这会吞掉正在传播的异常,而且编译器会为此发出SyntaxWarning(PEP 765)。
类型即文档
- 所有地方都使用完整、现代的类型注解:
list[str]、str | None、dict[str, int]。 - 对于反复使用的复杂类型,使用
type语句。 - 不要使用鸭子类型:如果在操作前要检查属性是否存在,说明类型提示范围太宽——应缩小范围。
不写文档字符串——名称就是文档
- 使用简短、明确的函数名和变量名。
- 注释只写不明显的原因。绝不要复述代码,也不要写复述签名的文档字符串。
- 长注释是代码异味——应重构或重命名,而不是加以解释。只有在确有不明显原因时才使用多行注释,绝不要用来叙述代码。
- 用垂直空白分隔相关代码行。
保持导入整洁
- 所有
import语句都放在文件顶部。 - 不要在函数内导入,也不要使用
try...except ImportError防护。(针对仓库的约定可在既有循环导入模式下放宽此要求。) - 假设所有依赖都已安装。
不用脏招
- 选择直接明了的方案。如果没有现成方案,就重新考虑设计。
- 不要对抗第三方框架——遵循其预期用法。
审查清单
风格
- 没有只使用一次的中间变量
- 在适当情况下使用列表推导式/标准库惯用写法
- 用垂直空白分组相关逻辑
类型标注
- 所有公开函数和方法都使用完整的现代类型注解
- 对复杂/重复使用的类型使用
type语句 - 不使用鸭子类型(不以
hasattr防护替代正确的类型)
导入
- 所有导入都放在文件顶部
- 没有
try...except ImportError代码块 - 没有函数级导入
OOP/设计
- 数据模型作为一等对象处理(不以普通字典传递)
- 工厂函数命名为
build_... - 应用逻辑放在方法中,而不是模块级函数中
- 对派生属性使用
@property/@cached_property
最佳实践
- 全程使用带时区信息的 UTC 日期时间
- 布尔参数前使用
, *, -
try代码块和上下文管理器尽可能简短(理想情况下各占一行)
架构健康度(模块级)
适用于差异中涉及的完整文件,而不仅是改动的行:
- 没有超过 500 LOC 的模块(按职责拆分)
- 没有包含超过 10 个模块级函数的模块(改用类)
- 模块级函数有充分理由——默认应使用类的方法
- 没有巨型模块(在单个文件中混杂无关职责,例如 CLI 接线、业务逻辑和子进程管理,应拆分)
-
pyproject.toml中没有超出python-boilerplate基线的复杂度规则抑制项(C901、PLR09xx) - 测试通过公共接口验证行为,而不是修补私有函数或断言子进程命令列表
测试
集成测试优先(不可妥协)
为正常路径编写集成测试,为边界情况编写单元测试。这样能最大限度地提高每行测试代码所带来的可信度。
- 集成测试让多个模块协同运行,并使用真实或近似真实的 I/O。它们能捕获最重要的问题:模块间契约失效、对状态的错误假设以及顺序问题。只模拟无法控制的内容(网络、外部进程、数据库)。
- 单元测试针对隔离的特定函数,但仅限于函数存在值得覆盖的边界情况(错误处理、边界值、复杂分支)。不要为简单的胶水代码编写单元测试。
- 不要重复覆盖。 如果集成测试已经覆盖某个正常路径,就不要再为同一路径编写单元测试。单元测试应覆盖集成测试无法高效触及的内容(少见的错误分支、边界情况)。
- 端到端测试(浏览器、全栈)应单独处理——它们属于前端或应用测试套件,而非库或基础设施代码。需要端到端测试用户可见行为时再编写。
测试简洁性(不可妥协)
测试必须易于阅读和维护。冗长的测试容易被匆匆略过、误解,或未经思考就复制粘贴。
- 每个概念只断言一次。 一个测试方法应只测试一种行为。如果多个断言验证的是同一种行为的不同方面,则可以同时使用。
- 用 fixture 处理设置,避免复制粘贴。 如果多个测试方法中重复出现设置代码,说明缺少 fixture 或参数化。
- 参数化优于复制粘贴。 当多个测试仅在输入/输出值上有所不同时,使用
@pytest.mark.parametrize。五个只差一个字符串的测试方法,应合并为一个参数化测试。 - 根据行为命名测试,而非根据方法命名。
test_returns_error_when_db_missing比test_db_import_3更好。 - 不要使用不必要的模拟。 仅模拟无法控制的内容(网络、时钟、外部进程)。过度模拟会让测试变成循环论证——测试的是模拟对象,而不是代码。
- 优先扁平结构,避免嵌套。 优先使用模块级测试函数或扁平的测试类。测试中的深层嵌套类层级会增加复杂性,却没有价值。
- 优先使用上下文管理器(
with patch(...)),而非monkeypatch。 上下文管理器能清晰地限定需要模拟的作用域。只有在确实能简化测试时才使用monkeypatch(例如环境变量、chdir,或修补生命周期超出测试主体的 fixture 上的属性)。
检查清单
- 测试文件路径与
src模块路径一致 - 测试类名和方法名能描述所测试的行为
- 集成测试覆盖正常路径;单元测试覆盖边界情况
- 集成测试与单元测试之间没有重复覆盖
- 当 3 个或更多测试仅在输入/输出上有所不同时,使用
@pytest.mark.parametrize - 重复的设置使用 fixture——不复制粘贴样板代码
- 仅针对外部边界(子进程、网络、时钟)使用模拟
上一节:Python 3.13
以上所有内容均针对 Python 3.14。使用 3.13 时:
- 没有 t-strings。 使用目标库自身的参数化或转义方式构建 SQL/HTML
(
cursor.execute(sql, params)、markupsafe),切勿使用 f-string 插值。 - 没有
compression.zstd。 可选方案是第三方zstandard包;tarfile/zipfile/shutil无法读取或写入 zstd。 - 注解会立即求值。 前向引用仍需要
from __future__ import annotations,且没有annotationlib——请使用typing.get_type_hints()。主路径的 ruff 配置会禁止该导入 (references/testing-and-tooling.md中的lint.flake8-tidy-imports.banned-api."__future__.annotations");项目目标为 3.13 时, 请删除这一项,改为 3.14 时再恢复。 - 多种类型的
except需要加括号:except (TimeoutError, ConnectionRefusedError):。 - 自由线程仍处于实验阶段,尚未获得官方支持,而且其单线程性能损失远大于 3.14 的约 5–10%。
- 项目目标为 3.13 时,请在 mypy/ty 配置中将
python_version/python-version固定为"3.13"。
评论
支持 Markdown