There are currently three different documentation styles supported by Sphinx: the original Sphinx style and the more recent NumPy and Google styles. The differences between them are mainly in style but it's actually slightly more than that.
The Sphinx style was developed using a bunch of reStructuredText roles, a very effective method but when used a lot it can be detrimental for readability. You can probably tell what the following does but it's not the nicest syntax:
:param amount: The amount of eggs to return :type amount: int
The Google style was (as the name suggests) developed by Google. The goal was to have a simple/readable format which works both as in-code documentation and parse able for Sphinx. In my opinion, this comes closer to the original idea of reStructuredText, a format that's very close to how you would document instinctively. This example has the same meaning as the Sphinx style example shown earlier:
Args: amount (int): The amount of eggs to return
The NumPy style was created specifically for the NumPy project. The NumPy project has many functions with a huge amount of documentation and generally a lot of documentation per argument. It is slightly more verbose than the Google format but quite easy to read as well:
Parameters ---------- amount : int The amount of eggs to return
In the future, with the Python 3.5 type hint annotations, at least the argument type part of these syntaxes might become useless. For the time being, Sphinx has no specific support for the annotations yet, so explicit type hinting through the docs must be used. But perhaps we can use the following soon:
def eggs(amount: int): pass
First of all, let's look at the traditional style, the Sphinx style. While it's easy to understand what all the parameters mean, it's a bit verbose and not all that readable. Nonetheless, it's pretty clear and definitely not a bad style to use:
class Spam(object): ''' The Spam object contains lots of spam :param arg: The arg is used for ... :type arg: str :param `*args`: The variable arguments are used for ... :param `**kwargs`: The keyword arguments are used for ... :ivar arg: This is where we store arg :vartype arg: str ''' def __init__(self, arg, *args, **kwargs): self.arg = arg def eggs(self, amount, cooked): '''We can't have spam without eggs, so here's the eggs :param amount: The amount of eggs to return :type amount: int :param bool cooked: Should the eggs be cooked? :raises: :class:`RuntimeError`: Out of eggs :returns: A bunch of eggs :rtype: Eggs ''' pass
This is a very useful output indeed with documented functions, classes, and arguments. And more importantly, the types are documented as well, resulting in a clickable link towards the actual type. An added advantage of specifying the type is that many editors understand the documentation and will provide auto-completion based on the given types.
To explain what's actually happening here, Sphinx has a few roles within the docstrings that offer hints as to what we are documenting.
The param
role paired with a name sets the documentation for the parameter with that name. The type
role paired with a name tells Sphinx the data type of the parameter. Both the roles are optional and the parameter simply won't have any added documentation if they are omitted, but the param
role is always required for any documentation to show. Simply adding the type
role without the param
role will result in no output whatsoever, so take note to always pair them.
The returns
role is similar to the param
role with regards to documenting. While the param
role documents a parameter, the returns
role documents the returned object. They are slightly different however. Opposed to the param
role, the returns
role is not dependent of the rtype
role or vice versa. They both work independently of each other making it possible to use either or both of the roles.
The rtype
, as you can expect, tells Sphinx (and several editors) what type of object is returned from the function.
The Google style is just a more legible version of the Sphinx style documentation. It doesn't actually support more or less but it's a lot more intuitive to use. The only thing to keep in mind is that it's a fairly recent feature of Sphinx. With the older versions, you were required to install the sphinxcontrib-napoleon
package. These days it comes bundled with Sphinx but still needs to be enabled through the conf.py
file. So, depending on the Sphinx version (Napoleon was added in Sphinx 1.3), you will need to add either sphinx.ext.napoleon
or sphinxcontrib.napoleon
to the extensions list in conf.py
.
Once you have everything configured correctly, we can use both the Google and NumPy style. Here's the Google style version of the Spam
class:
class Spam(object): ''' The Spam object contains lots of spam Args: arg (str): The arg is used for ... *args: The variable arguments are used for ... **kwargs: The keyword arguments are used for ... Attributes: arg (str): This is where we store arg, ''' def __init__(self, arg, *args, **kwargs): self.arg = arg def eggs(self, amount, cooked): '''We can't have spam without eggs, so here's the eggs Args: amount (int): The amount of eggs to return cooked (bool): Should the eggs be cooked? Raises: RuntimeError: Out of eggs Returns: Eggs: A bunch of eggs ''' pass
This is easier on the eyes than the Sphinx style and has the same amount of possibilities. For longer argument documentation, it's less than convenient though. Just imagine how a multiline description of amount
would look. That is why the NumPy style was developed, a lot of documentation for its arguments.
The NumPy style is meant for having a lot of documentation. Honestly, most people are too lazy for that, so for most projects it would not be a good fit. If you do plan to have extensive documentation of your functions and all their parameters, the NumPy style might be a good option for you. It's a bit more verbose than the Google style but it's very legible, especially with more detailed documentation. Just remember that, similar to the Google style, this requires the Napoleon extension for Sphinx, so make sure you have Sphinx 1.3 or above installed. Following is the NumPy version of the Spam
class:
class Spam(object): ''' The Spam object contains lots of spam Parameters ---------- arg : str The arg is used for ... *args The variable arguments are used for ... **kwargs The keyword arguments are used for ... Attributes ---------- arg : str This is where we store arg, ''' def __init__(self, arg, *args, **kwargs): self.arg = arg def eggs(self, amount, cooked): '''We can't have spam without eggs, so here's the eggs Parameters ---------- amount : int The amount of eggs to return cooked : bool Should the eggs be cooked? Raises ------ RuntimeError Out of eggs Returns ------- Eggs A bunch of eggs ''' pass
While the NumPy style definitely isn't bad, it's just very verbose. This example alone is about 1.5 times as long as the alternatives. So, for longer and more detailed documentation it's a very good choice, but if you're planning to have short documentation anyhow, just use the Google style instead.
For most projects, the Google style is the best choice since it is readable but not too verbose. If you are planning to use large amounts of documentation per parameter then the NumPy style might be a good option as well.
The only reason to choose the Sphinx style is legacy. Even though the Google style might be more legible, consistency is more important.