Python中将外部方法/对象的docstring移植到类中的正确方法是什么?
现有实现的合理性分析
你的核心诉求(避免文档重复编写、保证内外文档同步)是完全合理的,但当前写法存在两个明确问题:
- 定义顺序错误:当前代码中
bar的定义在Foo类之后,执行__init__.__doc__ += bar.__doc__时会抛出NameError,必须把bar的定义移到Foo类定义之前才能正常运行 - 属于轻度非规范写法:本质是利用Python动态性修改魔法属性,本身没有语法错误,但存在两个隐性问题:
- 静态文档生成工具(如Sphinx、pdoc)默认做静态代码扫描,不会执行这行运行时修改逻辑,可能导致生成的对外API文档缺失拼接的参数说明
- 直接拼接很容易出现格式混乱,比如两个docstring的缩进、换行规则不一致,拼接后可读性会大幅下降
该写法不属于严重违反规范的hack,小范围使用没有问题,但不推荐在正式对外发布的API项目中直接使用。
对外API场景的正确实现方式
推荐三种适配不同场景的方案,可根据项目规模选择:
方案1:调整顺序+优化拼接逻辑(改动最小)
先定义bar再定义Foo,同时给拼接的文档增加明确的分隔说明,避免用户混淆参数归属,适合小型不需要复杂静态文档的项目:
def bar(a, b): """ docstring of bar. a: int b: int """ print(a+b) class Foo: def __init__(self, **kwargs): """ Foo类初始化方法。 以下为透传给内部计算子例程的参数: """ self.sum = bar(**kwargs) __init__.__doc__ += bar.__doc__
方案2:封装通用装饰器(可复用性更强)
如果多个对外接口都需要复用内部子例程的文档,可以封装轻量装饰器实现文档拼接,避免到处写硬编码的__doc__修改逻辑:
def append_doc(doc_source, prefix="\n透传参数说明:\n"): def decorator(func): func.__doc__ = (func.__doc__ or "") + prefix + (doc_source.__doc__ or "") return func return decorator def bar(a, b): """ a: int b: int """ print(a+b) class Foo: @append_doc(bar) def __init__(self, **kwargs): """ Foo类初始化方法。 """ self.sum = bar(**kwargs)
方案3:用静态文档工具的引用能力(适合正式对外API)
如果你的API需要生成正式的在线文档,直接用文档工具自带的引用功能即可,不需要修改运行时代码:
- 以Sphinx为例,在Foo的
__init__docstring里加上参数说明参考 :func:bar`` 这类标记,生成文档时会自动关联对应说明,不需要重复写参数定义 - 这种方案完全符合Python开发规范,也不会出现运行时修改带来的兼容性问题
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

