如何在含@property的Python类中实现文档字符串装饰器?
解决@property文档字符串维度替换问题
核心思路
因为property对象是不可变的,无法直接修改其__doc__属性,所以要解决这个问题,得重新生成带替换后文档字符串的property对象,替换原类中的property属性。
方案一:修改类装饰器处理property
在你的类装饰器中,遍历类的所有属性,识别出property类型的成员,提取其getter/setter/deleter方法,替换文档字符串后重新创建property对象:
def class_doc_replace(dim): def decorator(cls): # 遍历类的所有属性 for attr_name, attr_value in list(cls.__dict__.items()): if isinstance(attr_value, property): # 提取原property的各个方法 getter = attr_value.fget setter = attr_value.fset deleter = attr_value.fdel # 替换getter的文档字符串(通常@property的doc存在于getter) if getter and getter.__doc__: new_doc = getter.__doc__.format(_GRID_DIM=dim) getter.__doc__ = new_doc # 重新创建property对象,替换原属性 setattr(cls, attr_name, property(getter, setter, deleter)) # 保留你原来处理普通方法的逻辑 elif callable(attr_value) and hasattr(attr_value, "__doc__"): if attr_value.__doc__: attr_value.__doc__ = attr_value.__doc__.format(_GRID_DIM=dim) return cls return decorator
使用示例:
@class_doc_replace(dim="ncv") class NCVData: @property def temperature(self): """获取温度数据,维度为{_GRID_DIM}""" return self._temp @class_doc_replace(dim="(nx, ny)") class GridData: @property def temperature(self): """获取温度数据,维度为{_GRID_DIM}""" return self._temp
调用help(NCVData.temperature)就能看到替换后的文档:获取温度数据,维度为ncv。
方案二:自定义可替换文档的property装饰器
如果不想修改类装饰器,可以单独写一个documented_property装饰器,结合类的维度属性来替换文档:
def documented_property(func): def wrapper(self): return func(self) # 保留原函数的文档作为模板 wrapper.__doc__ = func.__doc__ return property(wrapper)
然后在类装饰器中统一处理这个自定义property的文档替换:
@class_doc_replace(dim="ncv") class NCVData: @documented_property def temperature(self): """获取温度数据,维度为{_GRID_DIM}""" return self._temp
关键注意事项
- Python中自定义函数的
__doc__是可修改的,这是方案可行的基础;内置函数的__doc__只读,但你的@property getter都是自定义函数,不受影响。 - Sphinx生成文档时会读取类属性的
__doc__,重新生成的property对象带有替换后的文档,能被正确识别。 - 不要尝试直接修改原
property对象的__doc__,它是只读属性,会触发AttributeError。
内容的提问来源于stack exchange,提问作者Quixote
相关产品推荐
相关产品推荐

