如何在Python中记录类属性?
我正在写一个轻量级的类,这个类的属性是公开可访问的,并且在特定的实例中有时会被覆盖。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 个回答
你提到了PEP257文档字符串规范,在“什么是文档字符串”这一部分中提到:
在Python代码中出现的字符串字面量也可以作为文档说明。它们不会被Python的字节码编译器识别,也无法作为运行时对象的属性访问(也就是说,它们不会被赋值给
__doc__
),但是有两种额外的文档字符串可以被软件工具提取:在模块、类或
__init__
方法的顶层,紧接着简单赋值后出现的字符串字面量被称为“属性文档字符串”。
这一点在PEP 258: 属性文档字符串部分有更详细的解释。正如上面所说,属性并不是可以拥有__doc__
的对象,因此它们不会出现在help()
或pydoc中。这些文档字符串只能用于生成文档。
它们在Sphinx中使用,配合autoattribute指令。
Sphinx可以使用在赋值前一行的注释,或者在赋值后跟随的特殊注释,或者在定义后出现的文档字符串,这些都将被自动记录到文档中。
其他的回答已经非常过时了。PEP-257 讲述了如何为属性使用文档字符串。奇怪的是,它们是在属性之后出现的:
在Python代码的其他地方出现的字符串字面量也可以作为文档。它们不会被Python的字节码编译器识别,也不能作为运行时对象的属性访问(也就是说,它们不会被赋值给 __doc__),但是有两种额外的文档字符串可以被软件工具提取:
- 在模块、类或 __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 支持显示这些内容。
简单来说:类的属性不能像类和函数那样有文档字符串。
为了避免混淆,属性在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中,文档字符串实际上是它们所记录对象的成员,而不仅仅是源代码的注释。由于类属性变量本身不是对象,而是指向对象的引用,所以它们无法持有自己的文档字符串。我想你可以为引用的文档字符串辩护,也许是为了描述“这里应该放什么”,而不是“这里实际放了什么”,但我觉得在包含类的文档字符串中做到这一点已经足够简单了。