- 科学计算
【免费下载链接】qiskit
Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
导读
本文以 Qiskit 仓库中docs/_templates/autosummary/class.rst模板文件为核心,深入讲解 Qiskit 如何利用 Sphinx autosummary 扩展自动生成 Python 类的 API 参考页面,包括模板的 Jinja2 语法、成员过滤逻辑、继承成员处理,以及与docs/conf.py配置的联动机制。读完本文,你将掌握 Qiskit API 文档的生成链路,并能够在自己的 Sphinx 项目中复刻这套"模板驱动"的类文档方案。
一、模板在 Qiskit 文档体系中的位置
Qiskit 是一个面向量子电路、算符与 primitives 的开源 SDK,其 Python API 参考文档由 Sphinx 构建。整个文档构建的入口配置集中在docs/conf.py:
- 扩展列表中启用了
sphinx.ext.autodoc与sphinx.ext.autosummary(docs/conf.py); templates_path = ["_templates"](docs/conf.py)指向模板目录,Sphinx 会在这里查找 autosummary 使用的模板文件;autosummary_generate = True(docs/conf.py)表示构建时自动为.. autosummary::指令列出的对象生成 stub 文档页面;autosummary_generate_overwrite = False(docs/conf.py)表示已存在的 stub 文件不会被覆盖。
而docs/_templates/autosummary/目录下的class.rst正是 Sphinx 在生成类(class)stub 页面时使用的默认模板。它决定了每个类 API 参考页最终呈现哪些内容、以什么顺序呈现。
文档结构的顶层组织可见docs/index.rst,其中隐藏 toctree 挂载了 C API 参考(cdoc/index)、Python API 参考(apidoc/index)与 Release Notes;而docs/apidoc/index.rst则按模块分组(电路构造、量子信息、Transpilation、Primitives 与 Providers 等)列出所有 API 页面。每个类的参考页均由上述模板驱动生成。
二、class.rst模板逐段解析
先看模板的完整内容(docs/_templates/autosummary/class.rst):
{# We show all the class's methods and attributes on the same page. By default, we document all methods, including those defined by parent classes. -#} {{ objname | escape | underline }} .. currentmodule:: {{ module }} .. autoclass:: {{ objname }} :no-members: :show-inheritance: {% block attributes_summary %} {% if attributes %} .. rubric:: Attributes {% for item in attributes %} .. autoattribute:: {{ item }} {%- endfor %} {% endif %} {% endblock -%} {% block methods_summary %} {% set wanted_methods = (methods | reject('==', '__init__') | list) %} {% if wanted_methods %} .. rubric:: Methods {% for item in wanted_methods %} .. automethod:: {{ item }} {%- endfor %} {% endif %} {% endblock %}这个模板虽然只有 31 行,但完整定义了类文档页的四个组成部分。
2.1 页面标题:{{ objname | escape | underline }}
模板开头的 Jinja2 表达式把 autosummary 提供的objname(类全名,例如qiskit.circuit.QuantumCircuit)转义后,再由underline过滤器生成一个 RST 标题及下划线装饰行。这是 Sphinx autosummary 模板的标准做法:每个生成的 stub 页面顶部都会有一个以类名命名的标题。
2.2.. currentmodule:: {{ module }}
该指令将当前模块上下文切换为类所在的模块(module变量由 autosummary 注入,如qiskit.circuit)。后续所有.. autoattribute::、.. automethod::指令中写出的短名称都会在该模块下解析,从而避免在每个成员指令前重复写完整模块前缀。
2.3.. autoclass::与两个关键选项
.. autoclass:: {{ objname }} :no-members: :show-inheritance::no-members::关键设计。它禁止 autoclass 指令自身直接展开类的成员,成员的文档交由下方模板块中逐个.. autoattribute::/.. automethod::指令输出。这样可以在一个页面上同时展示属性与方法,并完全掌控它们的排列顺序与分组(先 Attributes 后 Methods)。:show-inheritance::在类文档中显示继承关系(基类列表),这与 docs/conf.py 中autodoc_default_options = {"show-inheritance": True}的默认行为一致。
此外,docs/conf.py 设置了autoclass_content = "both",即类的文档内容同时取自类 docstring 与__init__的 docstring;autodoc_typehints = "description"(docs/conf.py)把类型提示从签名挪到参数说明中,使签名行更易读。
2.4attributes_summary块:属性一览
{% block attributes_summary %} {% if attributes %} .. rubric:: Attributes {% for item in attributes %} .. autoattribute:: {{ item }} {%- endfor %} {% endif %} {% endblock -%}当 autosummary 检测到类存在attributes列表时,先输出.. rubric:: Attributes小节标题,然后对每个属性生成一条.. autoattribute::指令,由 autodoc 负责提取属性 docstring。注意:此模板对属性不做继承过滤——模板头部注释也明确说明"默认我们记录所有方法,包括父类定义的方法",即attributes中可能包含从基类继承来的属性。
2.5methods_summary块:方法一览与__init__过滤
{% block methods_summary %} {% set wanted_methods = (methods | reject('==', '__init__') | list) %} {% if wanted_methods %} .. rubric:: Methods {% for item in wanted_methods %} .. automethod:: {{ item }} {%- endfor %} {% endif %} {% endblock %}这是模板中最有技术含量的一行:
{% set wanted_methods = (methods | reject('==', '__init__') | list) %}它使用 Jinja2 的reject过滤器把methods列表中等于__init__的项剔除,再转回 list。原因在于:autoclass_content = "both"时__init__的 docstring 已经并入类文档,如果 Methods 小节再列出一个空的__init__条目会显得冗余。过滤后仅当剩余方法非空时才渲染.. rubric:: Methods小节,并对每个方法生成.. automethod::指令。
由此可以看出,class.rst的核心设计意图是:同一页面同时呈现类的属性与方法,方法区自动剔除__init__,属性与方法均允许包含继承成员。
三、姊妹模板class_no_inherited_members.rst:按需过滤继承成员
仓库中还存在一个功能几乎相同但行为不同的模板docs/_templates/autosummary/class_no_inherited_members.rst,其头部注释明确指出"除了set wanted_methods中的过滤逻辑外,与 class.rst 完全一致"。
两者差异集中在两个块:
{% block attributes_summary %} {% set wanted_attributes = (attributes | reject('in', inherited_members) | list) %} ... {% endblock %} {% block methods_summary %} {% set wanted_methods = (methods | reject('in', inherited_members) | reject('==', '__init__') | list) %} ... {% endblock %}区别对照如下:
| 过滤行为 | class.rst | class_no_inherited_members.rst |
|---|---|---|
剔除__init__ | ✅(methods) | ✅(methods) |
| 剔除继承来的属性 | ❌ 保留 | ✅reject('in', inherited_members) |
| 剔除继承来的方法 | ❌ 保留 | ✅reject('in', inherited_members) |
其中inherited_members是 Sphinx autosummary 在渲染模板时注入的变量,包含类从所有基类继承的成员名。reject('in', inherited_members)的含义是"丢弃那些出现在inherited_members列表中的项"。
因此,同一套 stub 生成机制可以通过选择不同的模板文件来获得两种文档风格:
- 默认模板:页面完整,含继承成员,适合一般类;
- 无继承模板:只展示类自身定义的成员,适合继承关系复杂、父类成员众多的类,避免页面过长或重复。
这一设计在 Qiskit 这类拥有庞大类层级(如QuantumCircuit、大量 Gate 类)的项目中非常实用:开发者可针对特定模块或类指定使用哪个模板,实现"一处模板、全局生效"。
四、与conf.py的联动:模板如何被启用与影响
4.1templates_path与 autosummary 模板发现
Sphinx autosummary 在渲染 stub 时会按照templates_path中声明的目录查找模板。Qiskit 的docs/conf.py设置了templates_path = ["_templates"],所以docs/_templates/autosummary/class.rst恰好命中 autosummary 对类模板的默认查找路径autosummary/class.rst。这意味着:只要把文件放在该路径下,所有通过.. autosummary::生成的类 stub 页面都会自动套用这份模板,无需在每个 rst 文件中单独声明。
4.2 stub 文件的生成与覆盖策略
docs/conf.py中:
autosummary_generate = True autosummary_generate_overwrite = Falseautosummary_generate = True:构建时对文档中出现的.. autosummary::指令自动生成对应 stub 文件(.rst或由autosummary_filename_map重命名);autosummary_generate_overwrite = False:已存在的 stub 文件不被覆盖,保证手写内容或历史生成的 stub 不被意外重写。
4.3 文件名冲突规避:autosummary_filename_map
由于 autosummary 依据导入名生成 stub 文件名,大小写仅不同的两个名称在 macOS 等大小写不敏感文件系统上会冲突。Qiskit 在 docs/conf.py 中通过映射手动避免:
autosummary_filename_map = { "qiskit.circuit.library.iqp": "qiskit.circuit.library.iqp_function", }这体现了模板机制之外,autosummary 配置对生成结果(文件名、页面)的直接影响。
4.4 docstring 风格与 napoleon 配置
模板生成的.. autoattribute::/.. automethod::指令最终由 autodoc 提取 docstring 渲染。Qiskit 在 docs/conf.py 中只启用 Google 风格 docstring 解析(napoleon_google_docstring = True、napoleon_numpy_docstring = False),并关闭# type:注释解析(autodoc_use_type_comments = False,docs/conf.py),以保证类继承成员的类型提示能被可靠识别——这直接影响模板中继承成员在页面上的呈现质量。
五、apidoc 页面如何触发模板渲染
模板本身不会自动产生内容,它依赖.. autosummary::指令触发。Qiskit 的docs/apidoc/index.rst通过 toctree 挂载各模块页面(如circuit、quantum_info、transpiler等),而模块页面内部再通过.. autosummary::列出具体类。例如docs/apidoc/circuit.rst:
.. automodule:: qiskit.circuit :no-members: :no-inherited-members: :no-special-members:模块级文档只做入口,不直接展开成员;成员类的详细页面由 autosummary 生成 stub 后,套用class.rst模板渲染。而docs/apidoc/root.rst则展示了一种更克制的用法——它明确注释"与其他 autosummary 指令不同,我们不设置:toctree:,不为此表生成 stub 文件",仅用.. autosummary::做交叉引用表,列出从根命名空间 re-export 的名称(如QuantumCircuit、transpile、QiskitError),真正的文档归属仍由各子模块页面负责。
5.1 特例:QuantumCircuit独立页面
在docs/apidoc/qiskit.circuit.QuantumCircuit.rst中可以看到另一种策略:
.. This is so big it gets its own page in the toctree, and because we don't want it to use autosummary. .. autoclass:: qiskit.circuit.QuantumCircuit :no-members: :no-inherited-members: :no-special-members: :class-doc-from: classQuantumCircuit是 Qiskit 中成员最多的核心类,stub 页面会过于庞大,因此它不经过 autosummary 模板,而是直接使用.. autoclass::在 toctree 中独占一页,并用:no-inherited-members:与:no-special-members:精简内容。这正好说明:模板机制是默认路径,但面对极端规模的对象,项目会主动选择绕过模板的专用方案——两种方式互为补充。
六、构建与验证:从 rst 到 HTML 的完整链路
文档构建入口在docs/Makefile:
SPHINXBUILD = sphinx-build SOURCEDIR = . BUILDDIR = _build在仓库docs/目录下执行make html(或make -f docs/Makefile html)即可触发完整构建。构建时 Sphinx 依次完成:
- 解析
conf.py加载 autodoc / autosummary 等扩展; - 扫描 apidoc 下各 rst 文件中的
.. autosummary::指令; - 对每个类生成 stub 文件(内容即
class.rst模板渲染结果); - 由 autodoc 逐个执行
.. autoattribute::/.. automethod::提取 docstring; - 输出到
_build/html/。
验证模板是否生效的快速方法是查看生成后的 stub 文件或 HTML 页面:若 Methods 小节没有空__init__条目、属性与方法分两个 rubric 呈现,即说明class.rst正确套用;若某类页面出现.. rubric::小节但无任何成员,则需检查该类 docstring 是否使用了 Google 风格(napoleon 只解析 Google 风格,见 docs/conf.py)。
七、在自有项目中的复用与定制建议
从 Qiskit 这套模板设计中可以提炼出可直接复用的经验:
- 模板命名与路径即约定:在
templates_path指向的目录下创建autosummary/class.rst,Sphinx 会自动用它渲染所有类 stub;不需要在每处.. autosummary::中额外声明。 - 成员分组渲染:用
attributes_summary/methods_summary两个可覆盖(overridable)块组织页面,配合rubric生成可读性极佳的分区标题。 - 过滤逻辑用 Jinja2 过滤器集中管理:
reject('==', '__init__')、reject('in', inherited_members)都写在模板内,改一处即全局生效。 - 多模板并行:仿照 Qiskit 提供
class.rst与class_no_inherited_members.rst两套模板,在 autosummary 指令层面按需选择,兼顾"信息完整"与"页面精简"。 - 为超大对象留后门:对成员过多的类直接使用
.. autoclass::独立成页,避免 stub 页面臃肿。
如果需要更细粒度的控制,还可以在 autosummary 指令中通过:template:选项显式指定自定义模板文件(例如:template: autosummary/class_no_inherited_members.rst),这正是 Qiskit 保留两个模板文件所能支撑的扩展方式。
结语
docs/_templates/autosummary/class.rst虽然只有 31 行,却是 Qiskit 庞大 API 文档体系的"类页面统一生成器":它用autoclass的:no-members:把成员渲染权交给模板,用两个 Jinja2 块控制属性/方法的分组展示,用reject过滤器剔除__init__,并通过templates_path全局生效。配合conf.py中 napoleon、autodoc 与 autosummary 的一系列配置,以及class_no_inherited_members.rst提供的继承过滤变体,Qiskit 得以在数百个类之间保持文档风格一致、内容完整且构建可控。理解这份模板,也就理解了"如何用模板驱动的方式为大型 Python 项目自动生成高质量 API 参考文档"这一通用工程实践。
- 科学计算
【免费下载链接】qiskit
Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
相关推荐
PyFlink 文档工程深度解析:Sphinx autosummary 类模板如何定制 PyFlink API 参考文档
PyFlink 文档工程深度解析:Sphinx autosummary 类模板如何定制 PyFlink API 参考文档 导读 本文聚焦 PyFlink(Fli
后端大数据流处理批处理Warp API 文档生成探秘:Sphinx autosummary 类模板 class.rst 的结构解析与定制实践
Warp API 文档生成探秘:Sphinx autosummary 类模板 class.rst 的结构解析与定制实践 Warp 的官方 API 参考文档(涵盖
高性能计算物理引擎图形学机器人深入解析 yfinance 文档体系:Sphinx autosummary 类模板 class.rst 的作用与定制指南
深入解析 yfinance 文档体系:Sphinx autosummary 类模板 class.rst 的作用与定制指南 导读 在 yfinance 这个"Py
数据分析金融科技
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考