88

I did not find any best practice about what should be documented in the class and __init__ docstrings. Sometimes I find that the constructor arguments are already documented in the class docstring, sometimes the are described in the __init__ docstring. I prefer describing the construction within the class docstring, as this is what you call when creating a new instance. But what should be documented in the __init__ methods docstring then?


edit:

I know about the google styleguide and the google docstring style example, but both do not answer my question. The docstring style example does say

The __init__ method may be documented in either the class level docstring, or as a docstring on the __init__ method itself. Either form is acceptable, but the two should not be mixed. Choose one convention to document the __init__ method and be consistent with it.

But if I choose to put the docstring of the __init__ function into the class level docstring, what should the __init__ docstring contain?

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
causa prima
  • 1,502
  • 1
  • 14
  • 24

7 Answers7

34

There is an official answer, in PEP 257 (the docstring PEP), which is arguably authoritative:

The class constructor should be documented in the docstring for its __init__ method.

This is quite logical, as this is the usual procedure for functions and methods, and __init__() is not an exception.

As a consequence, this puts the code and its documentation in the same place, which helps maintenance.

Finally, tools that display documentation to the user (like Jupyter, or the built-in Python shell command help()) are more likely to correctly display the documentation of your code. In practice, they do display the __init__() docstring automatically when you ask for help on the class, so this is one more reason to follow the official convention of putting the initialization documentation in __init__().

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
  • Unfortunately an end-user would never find this documentation, since they'll type `help(MyClass)` not `help(MyClass.__init__)` when they get stuck. So I personally think the PEP is not making the best suggestion, only following the rules. It would make sense if the `help(MyClass)` docstring had a mechanism for including/displaying the __init__ docstring. – Demis Sep 29 '19 at 22:28
  • 4
    Fortunately, this comment is not correct: `help(MyClass)` shows all the methods of the class, and `__init__()` is one of them, so the user does have the information they need for creating objects. This is consistent with the official requirement. Furthermore, a tool like the Jupyter notebook does something similar when you ask for the arguments of a class constructor (with shift+tab): it displays both the class _and the init docstring_. The moral is that following some common convention is very helpful—especially when it's a good one. – Eric O. Lebigot Oct 02 '19 at 09:37
  • 2
    You are correct, the PEP suggestion is pretty good then. I still don't like having to scroll to `__init__()` in the help output - again, this is a function the end user never sees, but is expected to know that it's invisibly remapped to the name of the class instead. In terms of doc readability/obviousness this is kind of ugly, but that's just programming for you I guess. Thanks for the correction, i'll just write "see __init__()" in my class's docstring for noobs (of which I'll have many using my modules). – Demis Dec 14 '19 at 05:19
  • 1
    Both Jupyter (through `MyClass?`) and Python (through `help(MyClass)`) automatically display the init docstring, so this should be pretty obvious. Since it's a standard, it's likely that users will see this in many other libraries, too. – Eric O. Lebigot Dec 15 '19 at 11:18
  • 3
    Interesting addition: Spyder automatically uses the contents of `ClassName.__doc__` for Tab-auto-completion when instancing the class, NOT the contents of `ClassName.__init__.__doc__`. So this makes documenting in the *class* much more useful to the end-user. Also as others said, NumpyDoc also says to document constructor in Class docstring. Lastly, `help(MyClass)` doesn't appear to put the `__init__` help at the top, making locating the constructor arguments irritating! – Demis Dec 16 '19 at 05:43
  • 2
    I would argue that both Spyder and NumpyDoc missed the fact that there is a convention, which has the non-desirable results that you observed. Personally I don't mind `help(MyClass)` putting the `__init__()` docstring at the bottom, since the command really asks for help on the class, and therefore information on what the class provides should come first. Whatever convention help-providing programs choose, the only way of getting a good and consistent behavior is for everybody to follow standards. – Eric O. Lebigot Dec 19 '19 at 12:13
  • There needs to be a PythonStudio. – Brian Wiley Dec 20 '20 at 09:08
20

The class documentation should include the public components of the object. The __init__ parameters may or may not be public, so whether they are included in the class docstring or not depends on the object design.

The full paragraph in PEP 257 states:

The docstring for a class should summarize its behavior and list the public methods and instance variables. If the class is intended to be subclassed, and has an additional interface for subclasses, this interface should be listed separately (in the docstring). The class constructor should be documented in the docstring for its __init__ method. Individual methods should be documented by their own docstring.

And the google style guide states:

Classes should have a docstring below the class definition describing the class. If your class has public attributes, they should be documented here in an Attributes section and follow the same formatting as a function’s Args section.

So the documentation determination hinges on whether the parameters for __init__ are public. If the intention of the object is for users to construct their own instances, the __init__ parameters should be documented in the class docstring. However, if an object is constructed internally then returned to the user, the class documentation should only refer to the public aspects of the object.

So the following example from google suggest that the likes_spam parameter from __init__ is public:

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""

However, below the public likes_spam attribute is determined during __init__ based on two internal parameters spam_count and like_threshold. So, likes_spam is documented in the class docstring, while spam_count and like_threshold are documented in the __init__ docstring.

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, spam_count, like_threshold=1):
        """Inits SampleClass.

        Args:
            spam_count: The amount of SPAM consumed.
            like_threshold: The threshold consumed that indicates 
                whether we like SPAM.
        """
        self.likes_spam = spam_count > like_threshold
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""
dshanahan
  • 676
  • 5
  • 12
15

The actual usage of the class is initialized by a command like SampleClass(args), and no user is ever going to type in SampleClass.__init__(args), so from an end-user perspective, when they are confused, they are much more likely to type

help(SampleClass)

instead of

help(SampleClass.__init__)

So I think it makes sense to put all documentation into SampleClass's docstring.
And in __init__'s docstring put "Please see help(SampleClass) for more info" just in case there's the off chance that someone (or some program) looks at it.

Demis
  • 5,278
  • 4
  • 23
  • 34
  • A user pointed out that `help(SampleClass)` does ALSO print out the help for `SampleClass.__init__()`, but unfortunately Spyder shows this line *at the Bottom of the list of methods*. In theory documenting constructor in `init__()` would be adequate, except still confusing since again the user never sees the term `__init__` and must know that this is invisibly remapped to `MyClass(args)`). In this comment: https://stackoverflow.com/questions/37019744/is-there-a-consensus-what-should-be-documented-in-the-classes-and-init-docst/57926574?noredirect=1#comment102775909_57926574 – Demis Jun 03 '21 at 15:46
9

I personally try to use the google styleguide when possible

When you create a new instance with __init__ it should be documented what member variables are initialized. Then other people know what they can expect when they need to access them later in their code.

Sample from the google styleguide:

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""
salomonderossi
  • 2,180
  • 14
  • 20
7

Numpy says you should document the __init__ in the class document. https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard

Here is an example you can see where __init__ doesn't have a docstring. Instead it shows up in the class document. https://github.com/numpy/numpy/blob/master/numpy/core/records.py

Brig
  • 10,211
  • 12
  • 47
  • 71
  • 2
    This goes against the official guideline from PEP 257. – Eric O. Lebigot Dec 15 '19 at 11:22
  • 1
    Spyder then also goes against the official guideline then, as it seems that Spyder gets it's tab-autocompletion text from the *class*, not the *__init__*. – Demis Dec 17 '19 at 07:33
  • 1
    I guess we should ask the question "*Why are major packages with an enormous userbase doing this differently from PEP 257 guidelines.*" I have seen SO users refer to numpy/numpydoc as "standards". Maybe there is a good reason. Are there other packages which also don't follow PEP 257? – Demis Dec 26 '19 at 18:24
  • 1
    @Demis Spyder does something weird for me. If I press Ctrl+I, it gets the class docstring. If I use `function?` it shows the class and then the `__call__` docstring, but if I type `function(` it shows a popup that starts in the middle of the `Returns` section of the class docstring... – endolith Oct 25 '20 at 23:00
  • This other question got some answers pointing out that Sphinx parses the docstring, I still don’t really understand how it does that. https://stackoverflow.com/review/suggested-edits/25144896 – Demis Oct 27 '20 at 00:19
1

I am not aware of any consensus on that point.

However, the sphinx autodoc module allows documentation to be generated from your docstring.Therefore it tends to enforce consistent docstring documentation.

In your case, I would document what the class is and the constructor arguments in the class docstring like:

class MyClass:
    """I am a class.
    I do funny stuff

    :type tags: dict
    :param tags: A dictionary of key-value pairs
    """

    def __init__(tags):
        self.tags = tags
Oleiade
  • 6,156
  • 4
  • 30
  • 42
  • 1
    Like I said, that's what I would prefere, too. But as most guides encourage you to also write docstrings for special functions, I wonder what the `__init__` docstring should contain, as all it should do is initialize a class instance. Also, with tools like sphinx, information written in the docstring of special functions won't show in the built documentation, if I'm not wrong. – causa prima May 04 '16 at 10:52
  • Well, as there is no consensus on that matter and as far as I know no official python documentation tackles it. I would tend to say, do as you think suits the best to your need. I think the real question here is why do you want to add docstring to special functions then (for what purpose)? I mean in which context? Is it for documenting the code, to generate docs? – Oleiade May 04 '16 at 11:04
0

Google has their own style guide for Python, which is not a bad thing to refer to. Here is a link with what they consider best practices for doc-strings: http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html

coralvanda
  • 6,431
  • 2
  • 15
  • 25
  • 1
    They don't answer my question, as I stated in my updated question. – causa prima May 04 '16 at 08:58
  • 2
    From your updated question: "But if I choose to put the docstring of the __init__ function into the class level docstring, what should the __init__ docstring contain?" Based on the style guide, in that case, your __init__ method should not have a docstring. – coralvanda May 04 '16 at 09:21