Python Docstrings As already pointed out in a previous article titled Commenting Python Code you have learned that documentation is an essential, and a continuous step in the process of software development. The article mentioned above briefly introduced the concept of docstrings which is a way to create documentation for your Python code from within the code. This in-code documentation works for modules, classes, methods, and functions, and it is the preferred way to document all Python code. There is a lot more to it, and that's why we will have a closer look at this subject in this article. We'll cover conventions on how to write docstrings correctly, as well as various docstring formats that are used in practice, followed by accessing a docstring from your Python script. And lastly, we'll present you a number of tools in order to use and evaluate docstrings.
Diving into Docstrings
The term docstring is an abbreviation for documentation string, and describes your source code - i.e. what your function, module, or class does. It is added as a regular comment right below the head of a function, module, class, or method. A typical example looks as follows, and is taken from a Python class for working with a measurement device like a mobile sensor to measure temperature, humidity, and wind velocity. Listing 1: Python code with a single-line docstring
class Device: def __init__(self, temp=0.0): "Initialize the Device object with the given temperature value." self.set_temperature(temp) return
In order to write a docstring correctly follow a number of conventions. These conventions are explained in more detail in the PEP 257, which stands for Python Enhancement Proposal.
Due to simplicity the docstring used in Listing 1 comes as a single-line comment. Keep in mind to begin the text of a docstring with a capital letter, and end it with a period. Based on the fact that code is typically read more often than it is written, it is recommended to describe what the documented structure does as a kind of command instead of how it is done. Mentioning which kind of value is returned to the caller helps to understand the result of the function or method. You may have noted that the method's docstring from Listing 1 is framed in single double-quotes. Well, as long as both the beginning and the end quotes are similar, Python is quite tolerant, and you are also allowed to use three single-quotes as well as three double-quotes, instead:
def get_temperature(self): '''Return the stored temperature value as a float value.''' return self.temperature def set_temperature(self, temp): """Set the temperature value.""" self.temperature = float(temp) return
Please make sure that the closing quotes are in the same line as with the opening quotes. Also, do not add any empty lines before, or after the text of the docstring.
Furthermore, a docstring can also be written as a multi-line comment. When using multi-line comments, two things change - the encapsulation of the docstring must be written in triple single- or double-quotes, and the structure of the docstring itself has a deeper meaning that is assigned to the entire text. The first line of the docstring is interpreted as an abstract, or a short description, and is recommended to be written in the same way as a single-line docstring. An empty line that follows is interpreted as a separator between the abstract and the full description below. Listing 2 extends Listing 1, and does not use a specific format for the description, as mentioned below. Listing 2: Multi-line docstring
def set_temperature(self, temp): """Set the temperature value. The value of the temp parameter is stored as a value in the class variable temperature. The given value is converted into a float value if not yet done. """ self.temperature = float(temp) return
Following the docstring structure for multi-line strings is strongly recommended as automated indexing tools evaluate these texts, and therefor rely on the compliance with the block order.
You might expect that there is just one binding docstring format. Unfortunately, there is more than one, and all of these format variants work with multi-line docstrings.
- reStructured text (reST) / Sphinx: This is the Official Python documentation standard. It uses the syntax of the lightweight markup language reStructured text (reST) which is similar in usage to Markdown.
- Google Docstrings: Google's style of docstring
- NumPy/SciPy Docstrings: A combination of reStructured text (reST) and Google Docstrings. Usable by Sphinx as well, and quite verbose.
Listing 3 shows how to write the docstring using reST. The keywords that you can use are the following:
type: Parameter and its variable type
rtype: Specify both the return value and type of the function or method
.. seealso::: Further reading
.. notes::: Add a note
.. warning::: Add a warning
The order of the entries is not fixed, but stick to the same order throughout your entire project. The entries for
warning are optional.
Listing 3: Multi-line docstring with reST data
def set_temperature(self, temp): """Set the temperature value. The value of the temp parameter is stored as a value in the class variable temperature. The given value is converted into a float value if not yet done. :param temp: the temperature value :type temp: float :return: no value :rtype: none """ self.temperature = float(temp) return
In order to understand Google's docstrings you may have a look at Listing 4. The format is less dense, and uses more horizontal space. Listing 4: Multi-line docstring (Google Format)
def set_temperature(self, temp): """Set the temperature value. The value of the temp parameter is stored as a value in the class variable temperature. The given value is converted into a float value if not yet done. Args: temp (float): the temperature value Returns: no value """ self.temperature = float(temp) return
Finally, Listing 5 shows the same method in NumPy docstring format. It uses more vertical space, and looks easier to read than the original format. Listing 5: Multi-line docstring (NumPy Format)
def set_temperature(self, temp): """Set the temperature value. The value of the temp parameter is stored as a value in the class variable temperature. The given value is converted into a float value if not yet done. Parameters ---------- temp : float the temperature value Returns ------- no value """ self.temperature = float(temp) return
In the Python interactive help system, the docstring is available via the
__doc__ attribute. Listing 6 shows how to use code to access the documentation string, which in our example is based on Listing 1.
Listing 6: Accessing the docstring value
>>> def set_temperature (self, temp): ... """Set the temperature value.""" ... temperature = float(temp) ... return ... >>> print(set_temperature.__doc__) Set the temperature value.
Tools to Use the Docstrings
There is a number of tools that auto-generate documentation from docstrings, such as Sphinx, Epydoc, Doxygen, PyDoc, pdoc, and the autodoc extension for Sphinx. Most of them generate HTML documents for local use.
Pydoc is part of the Python distribution, and derives information about a module for the console, a web browser, or as an HTML document. Inside the Python shell use the
help() function in order to learn more about a module, function, class, or method. Figure 1 shows the docstring from Listing 1 via the Python help system.
Figure 1: The extracted docstring
In order to see the built-in documentation for all of the Python modules that are installed locally, you may run pydoc as a local webserver. Using the parameter
-p followed by the port number starts a small webserver that is accessible using the given port. Listing 7 starts the pydoc server at port 1234, and Figure 2 shows the information extracted and made available by pydoc.
Listing 7: Running pydoc as a webserver
$ pydoc3 -p 1234 Server ready at http://localhost:1234/ Server commands: [b]rowser, [q]uit server> ...
Figure 2: The extracted docstring on a local webserver
Following the guidelines for documentation helps you and others to understand source code today and at a later time. Docstrings are used for more than that, for example for the generation of manuals. This idea in mind allows projects at a greater scale.Reference: stackabuse.com