views:

77

answers:

2

I'm writing a lightweight class whose attributes are intended to be publicly accessible, and only sometimes overridden in specific instantiations. There's no provision in the Python language for creating docstrings for class attributes, or any sort of attributes, for that matter. What is the accepted way, should there be one, to document these attributes? Currently I'm doing this sort of thing:

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)

This will result in the class's docstring containing the initial standard docstring section, as well as the lines added for each attribute via augmented assignment to __doc__.

Although this style doesn't seem to be expressly forbidden in the docstring style guidelines, it's also not mentioned as an option. The advantage here is that it provides a way to document attributes alongside their definitions, while still creating a presentable class docstring, and avoiding having to write comments that reiterate the information from the docstring. I'm still kind of annoyed that I have to actually write the attributes twice; I'm considering using the string representations of the values in the docstring to at least avoid duplication of the default values.

Is this a heinous breach of the ad hoc community conventions? Is it okay? Is there a better way? For example, it's possible to create a dictionary containing values and docstrings for the attributes and then add the contents to the class __dict__ and docstring towards the end of the class declaration; this would alleviate the need to type the attribute names and values twice. edit: this last idea is, I think, not actually possible, at least not without dynamically building the entire class from data, which seems like a really bad idea unless there's some other reason to do that.

I'm pretty new to python and still working out the details of coding style, so unrelated critiques are also welcome.

+4  A: 

To avoid confusion: the term property has a specific meaning in python. What you're talking about is what we call class attributes. Since they are always acted upon through their class, I find that it makes sense to document them within the class' doc string. Something like this:

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"

I think that's a lot easier on the eyes than the approach in your example. If I really wanted a copy of the attribute values to appear in the doc string, I would put them beside or below the description of each attribute.

Edit:

Keep in mind that in Python, doc strings are actual members of the objects they document, not merely source code annotations. Since class attribute variables are not objects themselves but references to objects, they have no way of holding doc strings of their own. I guess you could make a case for doc strings on references, perhaps to describe "what should go here" instead of "what is actually here", but I find it easy enough to do that in the containing class doc string.

Forest
I guess in most cases this is fine, since the attributes —thanks for the terminology correction— are succinctly enough declared that they can just be grouped at the beginning of the class declaration without making it impractical to flip back and forth to either {read both the documentation and the default value} or {update both instances of the documentation and/or default value}.
intuited
Also note that my example will cause the documentation for the attributes to appear in the class's docstring. I actually would prefer to put the documentation in docstrings of the attributes themselves, but this doesn't work for most builtin types.
intuited
Yes, my initial idea was to just declare e.g. `flight_speed = 691; flight_speed.__doc__ = "blah blah"`. I think this is what you're mentioning in your **edit**. Unfortunately, this doesn't work for instantiations of (most?) builtin types (like `int` in that example). It does work for instantiations of user-defined types. =========== There was actually a PEP (sorry, forget the number) which proposed adding docstrings for class/module attributes, but it was declined because they couldn't figure out a way to make it clear whether the docstrings were for the preceding or following attributes.
intuited
A: 

I would suggest using Sphinx constructs.

Christian Hausknecht
My main goal is to make it easier to read and maintain the code by keeping the documentation and initialization of class attributes in close proximity, while providing a standard docstring. I read through the basic gist of Sphinx, and while it seems interesting and useful, I don't see a way that it would help to resolve my main concern here.
intuited
And I don't see your problem? You just use the standard notation in doc strings as the official python documentation uses. That is basically the same answer like the one above, but with the hint, that there exist a special notation for stuff like that!Perhaps you should explain better, what you really wanna do!
Christian Hausknecht
Hmm, missed this comment. Mostly I want to be able to document attributes inline, next to the attributes themselves; that's why I split the class docstring the way I did in the example. The downside to that approach (other than the ugly syntax) is that it results in unnecessary repetition. I didn't get the impression that Sphinx would help to mitigate these issues.
intuited