如何获取Python中NamedTuple或dataclass字段的文档字符串?
可行的实现方法
你遇到的问题是因为当前的字段注释写法并没有绑定到字段本身,而是被合并到了类的文档字符串中,或者转dataclass时不会自动继承这些注释。这里提供两种可靠的解决方案:
方案1:解析NamedTuple类的__doc__字符串
你写的字段注释会被整合到类的__doc__属性里,所以可以通过解析这个文档字符串来提取字段对应的描述。示例代码如下:
import re from typing import NamedTuple class Config(NamedTuple): buy_fee: float """My field description...""" sell_fee: float """Fee charged when selling assets""" def get_namedtuple_field_docs(cls): if not cls.__doc__: return {} # 匹配字段定义行和后续的三重引号注释 pattern = re.compile(r'(\w+):\s+\w+\n\s+"""([^"]+)"""', re.MULTILINE) matches = pattern.findall(cls.__doc__) return {field: desc for field, desc in matches} # 使用示例 print(get_namedtuple_field_docs(Config)) # 输出: {'buy_fee': 'My field description...', 'sell_fee': 'Fee charged when selling assets'}
方案2:用Annotated给字段附加元数据(推荐)
如果你的Python版本是3.9及以上,或者可以安装typing_extensions库,推荐用Annotated直接给字段绑定描述信息,这种方式不需要解析字符串,更稳定可靠:
# Python 3.9+ 直接用 typing.Annotated;低于3.9先安装typing_extensions,再用from typing_extensions import Annotated from typing import NamedTuple, Annotated # 定义一个简单的标记类,用来存储字段描述 class FieldDesc: def __init__(self, desc): self.desc = desc class Config(NamedTuple): buy_fee: Annotated[float, FieldDesc("My field description...")] sell_fee: Annotated[float, FieldDesc("Fee charged when selling assets")] def get_annotated_field_docs(cls): field_docs = {} for field in cls._fields: annotation = cls.__annotations__[field] # 提取Annotated中的元数据 if hasattr(annotation, "__origin__") and annotation.__origin__ is Annotated: for meta in annotation.__args__[1:]: if isinstance(meta, FieldDesc): field_docs[field] = meta.desc break return field_docs # 使用示例 print(get_annotated_field_docs(Config)) # 输出: {'buy_fee': 'My field description...', 'sell_fee': 'Fee charged when selling assets'}
为什么之前的方法无效?
inspect.getdoc(getattr(cls, f))获取的是NamedTuple自动生成的字段别名的文档,这个别名本质是类的索引映射,所以默认文档是Alias for field number X,和你写的注释无关。- 转dataclass的方法无法传递原NamedTuple的字段注释,因为转换过程不会自动提取类文档字符串里的字段描述,所以
dataclasses.fields返回的字段没有文档信息。
内容的提问来源于stack exchange,提问作者Petr
相关产品推荐
相关产品推荐

