使用Sphinx生成文档时如何让子类继承父类的Docstring?
问题:Sphinx中Dataclass子类无法继承父类Attributes文档
问题场景
使用Sphinx生成文档时,Dataclass子类B无法继承父类A的Attributes部分文档,已配置autodoc_inherit_docstrings=True,且无法使用装饰器方案。
最小复现代码
父类与子类代码:
@dataclass class A(): """ Attributes: a: This is the variable 'a' """ a: int = 0 @dataclass class B(A): """ Attributes: b: This is the variable 'b' """ b: int = 0
Sphinx配置conf.py:
import os import sys sys.path.insert(0, os.path.abspath('../test_config')) extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.autodoc.typehints'] autodoc_inherit_docstrings = True
RST文件内容:
Classes =================== .. autoclass:: test_config.A() .. autoclass:: test_config.B() :members: :show-inheritance: :inherited-members:
原因分析
autodoc_inherit_docstrings=True仅控制类/方法级别的整体docstring继承,而sphinx.ext.napoleon在处理结构化的Attributes区块时,若子类自身定义了该区块,不会自动合并父类的属性文档。
解决方案
方案一:自定义Sphinx钩子合并属性文档(无业务代码侵入)
在conf.py中添加自定义处理函数,自动将父类的Attributes内容合并到子类的docstring中:
import os import sys sys.path.insert(0, os.path.abspath('../test_config')) from sphinx.ext.napoleon.docstring import GoogleDocstring extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.autodoc.typehints'] autodoc_inherit_docstrings = True def merge_parent_attributes(app, what, name, obj, options, lines): if what != 'class' or not hasattr(obj, '__bases__'): return # 遍历父类(跳过object) for base in obj.__bases__: if base is object: continue base_doc = base.__doc__ if not base_doc: continue # 解析父类docstring提取Attributes部分 base_google_doc = GoogleDocstring(base_doc) base_attr_lines = [] in_attr_block = False for line in base_google_doc.lines: stripped_line = line.strip() if stripped_line == 'Attributes:': in_attr_block = True base_attr_lines.append(line) elif in_attr_block: # 遇到非缩进的新区块则停止 if stripped_line and not line.startswith(' '): break base_attr_lines.append(line) if not base_attr_lines: continue # 找到子类docstring中的Attributes插入位置 insert_pos = len(lines) in_sub_attr_block = False for idx, line in enumerate(lines): if line.strip() == 'Attributes:': in_sub_attr_block = True insert_pos = idx + 1 break # 子类无Attributes区块则新增 if not in_sub_attr_block: lines.extend(['', 'Attributes:']) insert_pos = len(lines) # 插入父类属性(跳过父类的Attributes标题行) lines[insert_pos:insert_pos] = base_attr_lines[1:] def setup(app): app.connect('autodoc-process-docstring', merge_parent_attributes)
方案二:调整子类Docstring写法
去掉子类的Attributes:标题,直接在类docstring中写属性说明,Napoleon会自动合并父类Attributes并识别子类属性:
@dataclass class B(A): """ 类B的描述(可选) b: This is the variable 'b' """ b: int = 0
补充说明
Sphinx原生确实不支持结构化docstring区块(如Attributes)的自动合并,需通过自定义钩子或调整docstring写法实现。
内容的提问来源于stack exchange,提问作者Gokul
相关产品推荐
相关产品推荐

