如何在Python中记录类属性?

2024-04-25 05:39:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个轻量级类,该类的属性旨在公开访问,并且有时仅在特定的实例化中被重写。Python语言中没有为类属性或任何类型的属性创建docstring的规定。有没有一种公认的方法来记录这些属性?目前我正在做这样的事情:

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中值的字符串表示,以至少避免默认值的重复。

这是对特别社区公约的严重违反吗?没事吧?有更好的办法吗?例如,可以创建一个包含属性值和docstring的字典,然后在类声明的末尾将内容添加到类__dict__和docstring中;这将减少两次键入属性名称和值的需要。编辑:我认为最后一个想法实际上是不可能的,至少在没有从数据动态构建整个类的情况下是不可能的,除非有其他原因这样做,否则这看起来是一个非常糟糕的想法。

我对python还很陌生,仍然在研究编码风格的细节,所以不相关的评论也很受欢迎。


Tags: the方法doc属性that记录flightdocstring
3条回答

引用PEP257:Docstring约定,在What is a docstring一节中声明:

String literals occurring elsewhere in Python code may also act as documentation. They are not recognized by the Python bytecode compiler and are not accessible as runtime object attributes (i.e. not assigned to __doc__), but two types of extra docstrings may be extracted by software tools:

String literals occurring immediately after a simple assignment at the top level of a module, class, or __init__ method are called "attribute docstrings".

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

它们在狮身人面像中与directive autoattribute 一起使用

Sphinx可以在赋值之前的行上使用注释,或者在赋值之后使用特殊注释,或者在定义之后使用docstring,这些都将被自动记录。

你可以这样滥用财产。属性包含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的docstring:

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 interactivehelp将给出:

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的后续调用能够以某种方式相互通信,那么它可以自动决定一个长且不太可能的内部属性名。我肯定有办法实现这一点,但我不确定它们是否值得。

为了避免混淆:术语property在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字符串,也许可以用“what should go here”来代替“what is actual here”,但是我发现在包含类doc字符串中这样做是很容易的。

相关问题 更多 >