如何访问Python中按PEP258定义的实例属性文档字符串?
如何访问Python实例属性的文档字符串
首先要明确:PEP 258中提到的在__init__里给实例属性写文档字符串的写法,Python解释器并不会自动将这个字符串和实例属性绑定。你看到instance.i?显示str的文档,是因为self.i被赋值为字符串实例,而那个独立的文档字符串字面量只是__init__函数里的无关联语句,并没有和self.i建立绑定关系。
以下是几种可行的解决方案:
1. 使用dataclass(推荐,Python 3.7+)
如果是静态实例属性,dataclass原生支持字段的文档字符串,且能通过标准工具访问;动态属性则可以结合包装类处理:
from dataclasses import dataclass import inspect @dataclass class AClass: c: str = 'class attribute' """This is AClass.c's docstring.""" def __post_init__(self): # 用包装类给动态属性添加文档 class AttrWrapper: def __init__(self, value, doc): self.value = value self.__doc__ = doc def __str__(self): return str(self.value) self.i = AttrWrapper('instance attribute', "This is self.i's docstring.") instance = AClass() # 访问类属性文档 print(inspect.getdoc(AClass.c)) # 访问动态实例属性文档 print(instance.i.__doc__)
2. 手动包装实例属性
通过自定义包装类给动态属性添加__doc__,避开内置类型无法添加属性的限制:
class AClass: c = 'class attribute' """This is AClass.c's docstring.""" def __init__(self): class WrappedAttr: def __init__(self, value, doc): self.value = value self.__doc__ = doc # 实现魔术方法让包装类行为贴近原类型 def __repr__(self): return repr(self.value) def __eq__(self, other): return self.value == other self.i = WrappedAttr('instance attribute', "This is self.i's docstring.") instance = AClass() print(instance.i.__doc__) # 输出目标文档字符串
3. 解析源代码提取文档(不推荐,hacky方式)
如果一定要保留PEP 258的写法,可以通过解析__init__的源代码,提取赋值语句后的字符串:
import ast import inspect class AClass: def __init__(self): self.i = 'instance attribute' """This is self.i's docstring.""" # 提取并解析__init__的源代码 source_code = inspect.getsource(AClass.__init__) tree = ast.parse(source_code) # 遍历AST节点找到目标文档 for idx, node in enumerate(tree.body): if isinstance(node, ast.Assign) and len(node.targets) == 1: target = node.targets[0] if isinstance(target, ast.Attribute) and target.attr == 'i': if idx + 1 < len(tree.body): next_node = tree.body[idx+1] if isinstance(next_node, ast.Expr) and isinstance(next_node.value, ast.Constant): print(next_node.value.value) # 输出目标文档字符串
内容的提问来源于stack exchange,提问作者Maxence1402
相关产品推荐
相关产品推荐

