首页
/ TheAlgorithms/Python 贡献指南详解:编写可测试、带类型标注且能通过自动化 CI 的算法实现

TheAlgorithms/Python 贡献指南详解:编写可测试、带类型标注且能通过自动化 CI 的算法实现

2026-09-04 23:25:53作者:郦嵘贵Just

本文以 CONTRIBUTING.md 为核心,系统讲解 TheAlgorithms/Python 算法库对贡献者的完整要求:什么样的代码才算一个合格的“算法”、必须满足哪些命名、docstring、doctest 与类型标注规范,以及 pre-commit、ruff、mypy、pytest 等自动化工具链如何逐层拦截不合规的提交。读完本文,你可以按仓库实际执行的验证标准写出一次就能通过 CI 的 PR。

一、贡献前必须确认的三件事

仓库欢迎实现算法与数据结构的新贡献者,但要求提交者在发起 pull request 之前完整阅读贡献指南;对指南本身有疑义时,应通过 issue 明确说明(原文档中的 issue 入口、Gitter 社区链接属于外部社区页面,此处不再罗列)。

成为贡献者即表示确认以下三点:

  • 代码为本人独立完成,不抄袭——任何抄袭作品不会被合并;
  • 提交的工作在 PR 合并后将以 MIT License 分发,对应仓库根目录的 LICENSE.md
  • 提交内容满足(或基本满足)仓库的编码风格与标准。

关于“做什么”的边界,指南划得很清楚:

  • 欢迎全新实现:同一问题的新解法、图数据结构的另一种表示、复杂度不同的算法设计;
  • 不允许对已有实现的完全相同复制。提交前必须先自查该解法是否已经存在(可检索目录导航 DIRECTORY.md);
  • 改进注释、补写规范测试同样是高价值贡献,与实现复杂算法同等被欢迎。

二、仓库对“算法”的操作性定义

这是贡献前最关键的判定标准。仓库认为一个算法是一或多个函数(或类),它应当:

  1. 接收一个或多个输入;
  2. 执行内部计算或数据操作;
  3. 返回一个或多个输出;
  4. 副作用最小化(如 print()plot()read()write() 都应避免)。

进一步地,算法应满足以下八条要求:

  • 类名与函数名直观,读者一眼能看懂用途;
  • 遵循 Python 命名约定,变量名直觉化;
  • 灵活地接受不同的输入值;
  • 输入参数与返回值带 Python 类型标注(type hints);
  • 对错误输入抛出 Python 异常(如 ValueError);
  • 带 docstring,清晰解释算法或给出来源资料链接;
  • 包含覆盖合法输入与错误输入的 doctest;
  • 返回计算结果,而不是打印或绘图。

指南还特别强调:仓库中的算法不应是现成 Python 第三方库的 how-to 示例,而应自己完成把输入转换为输出的计算;可以使用第三方库的数据类型、类或函数,但每个算法必须提供独特价值。这条规则解释了为什么仓库的 maths/sorts/ 等目录下的实现几乎都是纯计算逻辑。

三、本地自动化第一道关卡:pre-commit

指南建议使用 pre-commit 钩子在每次 commit 时自动按仓库风格修正代码:

python3 -m pip install pre-commit  # 仅首次需要
pre-commit install

安装后插件会在每次 commit 时运行;如发现问题,修复后再提交。也可以手动对全部文件强制执行:

pre-commit run --all-files --show-diff-on-failure

当前仓库的 .pre-commit-config.yaml 给出了这套钩子的完整清单,可作为“提交前会被检查什么”的权威参照:

  • pre-commit-hookscheck-tomlcheck-yamlend-of-file-fixer(仅 Python 文件)、trailing-whitespacecheck-executables-have-shebangsrequirements-txt-fixer
  • auto-walrus:自动简化海象运算符写法;
  • astral-sh/ruff-pre-commitruff-checkruff-format 两个钩子,即 lint 与格式化;
  • codespell:拼写检查(词表与跳过规则配置在 pyproject.toml[tool.codespell] 段);
  • pyproject-fmtvalidate-pyproject:保持 pyproject.toml 格式与合法性;
  • local 钩子 validate-filenames:直接执行 scripts/validate_filenames.py
  • prettier:对 TOML/YAML 文件做格式化。

其中 validate-filenames 钩子把指南中“文件名严格使用 snake_case”的要求变成了硬校验。从 scripts/validate_filenames.py 的源码看,它会遍历所有合法文件路径,逐一检测大写字母、空格、连字符以及未放入目录的散文件,任一违规即以非零退出码终止钩子。这正是指南第 7 节“strictly use snake_case”的机器实现。

四、编码风格:命名、版本、格式化与 Lint

4.1 Python 版本基线

指南正文写的是“请使用 Python 3.13+”(例如 print "Hello" 已不可用,必须 print("Hello"))。需要注意当前仓库的实际情况已经前进:pyproject.toml 声明 requires-python = ">=3.14",ruff 的 target-version = "py314"、mypy 的 python_version = "3.14" 均以 3.14 为准;CI 工作流 .github/workflows/build.ymlsetup-python 安装的也是 3.14。也就是说,文档写 3.13+ 是下限要求,而当前仓库代码与 CI 的实际运行基线是 Python 3.14,新提交建议直接按 3.14 的语法能力来写。

4.2 命名规范

  • 高度重视函数、类、变量命名,用描述性名称替代冗余注释;
  • 避免单字母变量名,除非其生命周期只有几行;
  • 缩写要展开:gcd() 难以理解,而 greatest_common_divisor() 不会;
  • 遵循 Python 命名约定:变量与函数用小写下划线(lower_case),常量全大写(UPPERCASE),类名 CamelCase。

这一条与 ruff 的 N(pep8-naming)规则组直接对应:pyproject.tomllint.select 启用了 NPL 等命名相关规则组。

4.3 字符串格式化、black 与 ruff

  • 鼓励在能提升可读性时使用 f-string;
  • 建议在提交前用 PSF 的 black 格式化(指南说明其尚非强制,但能自动对齐 PEP 8 的多数要求):
python3 -m pip install black  # 仅首次需要
black .
  • 所有提交必须通过 ruff 检查才会被接受,因此务必在本地先跑:
python3 -m pip install ruff  # 仅首次需要
ruff check

当前仓库的 ruff 配置远比默认严格:pyproject.tomllint.select 启用了约 40 个规则组,涵盖 F(Pyflakes)、E/W(pycodestyle)、B(bugbear)、S(bandit 安全)、SIM(简化)、UP(pyupgrade)、N(命名)、I(isort)等,同时按注释显式保留了一批“暂不修复”的规则(如 S101 允许 assert,与 doctest 风格兼容)。此外还有若干量化上限,例如 McCabe 圈复杂度上限被放宽到 17(lint.mccabe.max-complexity = 17),pylint.max-branches = 20。另有独立工作流 .github/workflows/ruff.yml 在 CI 中执行 ruff,与指南“All submissions will need to pass the test ruff .”相互印证。

4.4 docstring 与注释的合格线

  • 原创代码提交必须带 docstring 或注释说明工作内容;
  • 若参考了 Wikipedia 等来源,请把 URL 写进 docstring 或注释帮助读者溯源(.github/pull_request_template.md 的清单也要求“所有新算法至少包含一个指向 Wikipedia 或类似解释页面的 URL”);
  • 过细的注释会被打回,例如:
x = x + 2  # increased by 2

这种注释过于琐碎;注释应当有解释价值,且位置(行上/行尾/行下)在同一代码块内保持一致。

指南给出的 docstring 正例(注意缩进):

def sum_ab(a, b):
    """
    Return the sum of two integers a and b.
    """
    return a + b

4.5 doctest:被 pytest 自动采集的文档测试

指南强烈建议所有函数都写 doctest,并给出完整示例:

def sum_ab(a, b):
    """
    Return the sum of two integers a and b
    >>> sum_ab(2, 2)
    4
    >>> sum_ab(-2, 3)
    1
    >>> sum_ab(4.9, 5.1)
    10.0
    """
    return a + b

这些 doctest 会被 pytest 作为自动化测试的一部分运行,因此提交前应在本地确认它们能被发现并通过:

python3 -m doctest -v my_submission.py

这条要求并非空话。从 pyproject.toml 的 pytest 配置看,ini_options.addopts 中全局启用了 --doctest-modules,意味着 pytest 对每个模块都会执行 doctest 收集;.github/workflows/build.yml 的测试步骤正是 uv run --with=pytest-run-parallel pytest ... --cov=. .,doctest 失败等同于 CI 失败。同时 PR 模板明确要求“All functions have doctests that pass the automated testing”。

4.6 input() 的使用约束

  • 内置 input() 不鼓励使用,尤其禁止 input = eval(input(...)) 这类危险写法:
input('Enter your input:')
# Or even worse...
input = eval(input("Enter your input: "))
  • 如果确需 input(),应优雅处理首尾空白,追加 .strip()
starting_value = int(input("Please enter a starting value: ").strip())

4.7 类型标注与 mypy

  • 建议为函数参数与返回值添加类型标注,因为自动化测试会运行 mypy:
def sum_ab(a: int, b: int) -> int:
    return a + b
  • 本地检查命令:
mypy --ignore-missing-imports .              # 测试所有文件
mypy --ignore-missing-imports path/to/file.py # 测试单个文件
  • pyproject.toml[tool.mypy]python_version 固定为 3.14。需要说明的现状是:当前 .pre-commit-config.yaml 中的 mypy 钩子处于注释状态,但指南仍将 mypy 列为提交前必查项,PR 模板也把“所有函数参数与返回值带类型标注”列入检查清单,因此本地手动跑 mypy 仍是实际要求

4.8 其他风格条款

  • 列表推导式与生成器优先于 lambdamapfilterreduce,但核心是展示易读易维护的 Python;
  • 基础算法避免引入外部库,复杂算法才允许使用第三方库;
  • 指南原文要求“需要 requirements.txt 中不存在的第三方模块时,请把它加入该文件”。对照当前仓库实际状态:根目录已不存在 requirements.txt,依赖改由 pyproject.tomldependencies 声明并用 uv.lock 锁定(CI 通过 uv sync --group=test 安装)。因此新增依赖的正确做法是在 pyproject.toml 中声明并更新锁文件。

五、Issue 工作流:不指派、不占坑、用 Fixes # 自动关闭

指南对 issue 的处理方式有三条硬规则:

  1. 想解决某个 open issue,直接提交带修复方案的 PR 即可——本仓库不指派 issue,不要请求许可;
  2. 不要为“想贡献某个算法”而开 issue,应直接提 PR;
  3. 为保持 issue 列表精简,解决某个 issue 的 PR 必须在描述中写入关闭关键字。例如 PR 修复 issue #10,则描述中加入:
Fixes #10

GitHub 会在 PR 合并时据此自动关闭该 issue。.github/pull_request_template.md 的最后一条检查项也要求 PR 描述包含 Fixes #ISSUE-NUMBER 形式的关闭关键字,两者口径一致。

六、其余提交要求:目录、命名与自动生成文件

  • project_euler/ 目录提交代码前,必须先阅读该目录的专门指南 project_euler/README.md
  • 代码文件扩展名必须是 .py,Jupyter Notebook 不归本仓库收录;
  • 文件名严格使用 snake_case(下划线分隔),便于脚本解析——如前所述,这一条由 validate-filenames 钩子机器强制;
  • 尽量避免新建目录,优先把代码放入现有目录结构,并跟随目标文件夹内部已有的惯例;
  • 修改/新增代码后,提交前确认代码可编译运行;修改/新增文档则要求语言简洁、无语法错误;
  • 不要手动更新 README.md 或 DIRECTORY.md——两者由 GitHub Actions 定期自动生成。从源码可印证:.github/workflows/build.yml 在测试成功后执行 scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md,由 scripts/build_directory_md.py 重建目录导航;
  • 所有提交都会被 mypy 测试,鼓励在有意义处添加类型标注;
  • 指南最后强调:提交时请始终一致地遵守这些准则。

七、这些要求如何被 CI 与运维脚本实际执行

把 CONTRIBUTING.md 的条款放回仓库基础设施中,可以看到一条完整的“文档—工具—CI—运维”闭环:

  1. pytest 主测试流.github/workflows/build.ymlubuntu-latest 上安装 Python 3.14、用 uv 同步 test 依赖组后,以 pytest-run-parallel 并行执行全仓测试(--doctest-modulespyproject.toml 全局开启),并附 --cov 覆盖率报告;同时 --ignore 掉若干依赖网络或重模型的例外文件(如 web_programming/current_stock_price.pymachine_learning/lstm/lstm_prediction.pyproject_euler/ 等)。这正是指南所说“提交后在 PR 页面底部观察 Actions 测试、失败时点 details 查看输出”的测试来源。
  2. ruff 独立工作流.github/workflows/ruff.yml 单独保证 lint 关卡。
  3. PR 模板即验收清单.github/pull_request_template.md 把“原创声明、单一 PR 只改一个算法文件、文件放入现有目录、全小写无空格无连字符的文件名、命名规范、类型标注、doctest 通过、含 Wikipedia 链接、Fixes # 关键字”全部显式列成 checkbox,与本文各节条款一一对应。
  4. 超量 PR 的批量清理:维护者还依据 CONTRIBUTING.md 的硬性标准编写了运维脚本。从 scripts/README.md 看,close_pull_requests_with_require_tests.shclose_pull_requests_with_require_type_hints.shclose_pull_requests_with_require_descriptive_names.shclose_pull_requests_with_failing_tests.sh 等脚本用于关闭不满足“测试、类型标注、描述性命名”要求的 PR——这解释了为什么指南中 doctest 与 type hints 不是建议而是准入门槛。

八、小结:一份可直接执行的提交前检查清单

综合 CONTRIBUTING.md 全文与仓库工具链现状,一次合格的提交前应完成:

  1. 确认解法不与现有实现重复,且代码放在现有目录中;
  2. 文件名全小写 snake_case,无空格、连字符或大写(validate-filenames 会拦截);
  3. 函数/类命名描述化,参数与返回值带类型标注,错误输入抛异常;
  4. 每个函数写 docstring(含来源 URL)与覆盖正误输入的 doctest,并本地跑 python3 -m doctest -v <file> 验证;
  5. 本地执行 pre-commit run --all-files --show-diff-on-failure,保证 ruff check/format、拼写与 TOML/YAML 检查全部通过;
  6. 本地执行 ruff checkmypy --ignore-missing-imports <file>
  7. 若解决 issue,在 PR 描述写入 Fixes #N
  8. 不要改动 README.md / DIRECTORY.md,不要新建目录。

按这条清单提交,你的 PR 就能与 pyproject.toml.pre-commit-config.yaml.github/workflows/build.yml 所定义的验证体系完整对齐,一次通过自动化测试。

登录后查看全文
热门项目推荐
相关项目推荐