如何在Python中记录类属性?

179 投票
5 回答
131435 浏览
提问于 2025-04-16 00:02

我正在写一个轻量级的类,这个类的属性是公开可访问的,并且在特定的实例中有时会被覆盖。Python语言并没有提供为类属性或任何其他属性创建文档字符串的功能。那么,应该有什么样的方式来记录这些属性呢?目前我在做的事情是:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
    """

    flight_speed = 691
    __doc__ += """
        flight_speed (691)
          The maximum speed that such a bird can attain.
    """

    nesting_grounds = "Raymond Luxury-Yacht"
    __doc__ += """
        nesting_grounds ("Raymond Luxury-Yacht")
          The locale where these birds congregate to reproduce.
    """

    def __init__(self, **keyargs):
        """Initialize the Albatross from the keyword arguments."""
        self.__dict__.update(keyargs)

这样做会让类的文档字符串包含最初的标准文档部分,以及通过增强赋值添加的每个属性的描述。

虽然这种写法在文档字符串风格指南中似乎没有被明确禁止,但也没有被提到作为一种选择。这样做的好处是可以在定义属性的同时记录它们,而不需要写重复的注释来说明文档字符串中的信息。不过,我还是有点烦恼,因为我必须把属性写两遍;我在考虑在文档字符串中使用默认值的字符串表示,至少可以避免重复。

这样做算不算违反社区的约定呢?这样做可以吗?有没有更好的方法?比如,可以创建一个字典,里面包含属性的值和文档字符串,然后在类声明的末尾把这些内容添加到类的__dict__和文档字符串中;这样就不需要重复输入属性的名称和值了。编辑:我觉得这个最后的想法实际上是不可行的,至少在不动态构建整个类的情况下,这样做似乎是个坏主意,除非有其他原因这么做。

我对Python还很陌生,仍在摸索编码风格的细节,所以任何不相关的建议也欢迎。

5 个回答

51

你提到了PEP257文档字符串规范,在“什么是文档字符串”这一部分中提到:

在Python代码中出现的字符串字面量也可以作为文档说明。它们不会被Python的字节码编译器识别,也无法作为运行时对象的属性访问(也就是说,它们不会被赋值给__doc__),但是有两种额外的文档字符串可以被软件工具提取:

在模块、类或__init__方法的顶层,紧接着简单赋值后出现的字符串字面量被称为“属性文档字符串”。

这一点在PEP 258: 属性文档字符串部分有更详细的解释。正如上面所说,属性并不是可以拥有__doc__的对象,因此它们不会出现在help()或pydoc中。这些文档字符串只能用于生成文档。

它们在Sphinx中使用,配合autoattribute指令

Sphinx可以使用在赋值前一行的注释,或者在赋值后跟随的特殊注释,或者在定义后出现的文档字符串,这些都将被自动记录到文档中。

61

其他的回答已经非常过时了。PEP-257 讲述了如何为属性使用文档字符串。奇怪的是,它们是在属性之后出现的:

在Python代码的其他地方出现的字符串字面量也可以作为文档。它们不会被Python的字节码编译器识别,也不能作为运行时对象的属性访问(也就是说,它们不会被赋值给 __doc__),但是有两种额外的文档字符串可以被软件工具提取:

  1. 在模块、类或 __init__ 方法的顶层,简单赋值后立即出现的字符串字面量被称为“属性文档字符串”。
class C:
    "class C doc-string"

    a = 1
    "attribute C.a doc-string (1)"

    b = 2
    "attribute C.b doc-string (2)"

这同样适用于类型注解,像这样:

class C:
    "class C doc-string"

    a: int
    "attribute C.a doc-string (1)"

    b: str
    "attribute C.b doc-string (2)"

VSCode 支持显示这些内容。

131

简单来说:类的属性不能像类和函数那样有文档字符串。

为了避免混淆,属性在Python中有一个特定的含义。你说的其实是我们称之为类属性的东西。因为这些属性总是通过它们的类来使用,所以我觉得在类的文档字符串中记录它们是有道理的。可以这样做:

class Albatross(object):
    """A bird with a flight speed exceeding that of an unladen swallow.

    Attributes:
        flight_speed     The maximum speed that such a bird can attain.
        nesting_grounds  The locale where these birds congregate to reproduce.
    """
    flight_speed = 691
    nesting_grounds = "Throatwarbler Man Grove"

我觉得这样比你例子中的方法看起来要好很多。如果我真的想让属性值出现在文档字符串中,我会把它们放在每个属性描述的旁边或下面。

记住,在Python中,文档字符串实际上是它们所记录对象的成员,而不仅仅是源代码的注释。由于类属性变量本身不是对象,而是指向对象的引用,所以它们无法持有自己的文档字符串。我想你可以为引用的文档字符串辩护,也许是为了描述“这里应该放什么”,而不是“这里实际放了什么”,但我觉得在包含类的文档字符串中做到这一点已经足够简单了。

撰写回答