如何在Python中记录类属性?

时间:2010-06-16 06:58:53

标签: python class documentation docstring class-attributes

我正在编写一个轻量级类,其属性旨在可公开访问,并且有时仅在特定实例中被覆盖。在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)

这将导致类的docstring包含初始标准docstring部分,以及通过增强赋值为__doc__为每个属性添加的行。

虽然docstring style guidelines中似乎没有明确禁止这种风格,但它也没有作为选项提及。这里的优点是它提供了一种方法来记录属性及其定义,同时仍然创建一个可呈现的类docstring,并避免编写重复来自docstring的信息的注释。我仍然有点恼火,我必须实际写两次属性;我正在考虑使用docstring中值的字符串表示来至少避免重复默认值。

这是否是对特设社区公约的骇人听闻的违反?好吗?有没有更好的办法?例如,可以创建包含属性值和文档字符串的字典,然后将内容添加到类__dict__和docstring中,直到类声明的末尾;这样可以减少两次输入属性名称和值的需要。 编辑:我认为,最后一个想法实际上是不可能的,至少不是没有从数据动态构建整个类,这似乎是一个非常糟糕的想法,除非有其他理由这样做。< / p>

我对python很新,并且仍然在研究编码风格的细节,所以也欢迎不相关的批评。

3 个答案:

答案 0 :(得分:71)

为避免混淆:术语属性在python中有specific meaning。你所说的是我们所说的class attributes。由于他们总是通过他们的班级采取行动,我发现在类的doc字符串中记录它们是有意义的。像这样:

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"

我认为眼睛比你的例子中的方法容易得多。如果我真的想要在doc字符串中显示属性值的副本,我会将它们放在每个属性的描述旁边或下面。

请记住,在Python中,doc字符串是他们记录的对象的实际成员,而不仅仅是源代码注释。由于类属性变量本身不是对象,而是对对象的引用,因此它们无法保存自己的文档字符串。我想你可以为引用上的doc字符串做一个案例,也许是为了描述“应该去哪里”而不是“实际上是什么”,但我发现在包含类doc字符串中这样做很容易。

答案 1 :(得分:25)

您引用了PEP257:Docstring约定,在What is a docstring部分中说明:

  

Python代码中其他地方出现的字符串文字也可以作为文档。它们不被Python字节码编译器识别,并且不能作为运行时对象属性访问(即未分配给__doc__),但软件工具可以提取两种类型的额外文档字符串:

     

在模块,类或__init__方法的顶层进行简单赋值后立即出现的字符串文字称为“属性docstrings”。

这在PEP 258:属性文档字符串中有更详细的解释。 如上所述ʇsәɹoɈ。 属性不是可以拥有__doc__的对象,因此它们不会出现在help()或pydoc中。这些文档字符串只能用于生成的文档。

它们在Sphinx中使用directive autoattribute

Sphinx可以在作业之前的一行上使用注释,也可以在作业后使用特殊注释或在自动记录定义之后使用docstring。

答案 2 :(得分:11)

您可以滥用属性来达到此效果。属性包含getter,setter,deleter,和docstring 。天真的,这会变得非常冗长:

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """Docstring goes here."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

然后你将拥有一个属于C.x的文档字符串:

In [24]: print(C.x.__doc__)
Docstring goes here.

为许多属性执行此操作非常麻烦,但您可以设想一个辅助函数myprop:

def myprop(x, doc):
    def getx(self):
        return getattr(self, '_' + x)

    def setx(self, val):
        setattr(self, '_' + x, val)

    def delx(self):
        delattr(self, '_' + x)

    return property(getx, setx, delx, doc)

class C:
    a = myprop("a", "Hi, I'm A!")
    b = myprop("b", "Hi, I'm B!")

In [44]: c = C()

In [46]: c.b = 42

In [47]: c.b
Out[47]: 42

In [49]: print(C.b.__doc__)
Hi, I'm B!

然后,调用Pythons interactive help将给出:

Help on class C in module __main__:

class C
 |  Data descriptors defined here:
 |  
 |  a
 |      Hi, I'm A!
 |  
 |  b
 |      Hi, I'm B!

我认为应该是你所追求的。

编辑:我现在意识到我们可以避免将第一个参数传递给myprop,因为内部名称并不重要。如果myprop的后续调用可以某种方式相互通信,它可以自动决定一个长且不太可能的内部属性名称。我确信有办法实现这一点,但我不确定它们是否值得。