Table of Contents
- Docstring Styles
- Optimizing readability
- How to document a class
- How to document a function
1.1 What are docstrings
Okay, so many of you may be asking "What is a docstring, I've never heard of it", (if you have, then all the better). Well, docstrings are rather like comments e.g.
# This be a comment. However, as you may know well, trying to explain what a
class does in a one-line comment can be quite difficult. Here's an example of what can happen if you do
def lowerfirst(string): # This function takes an input string, and if the string is equal to the word "I", it will simply return that word # However, if the string is not equal to "I", it will attempt to lower the first letter by assigning it to a temporary # variable, tmp, and will then append all following letters to it, returning this value once finished # WARNING: This will break if the word given is only 1 letter long and not equal to "I" if string == "I": return string else: tmp = string.lower() for i in range(1,len(str)): tmp += i return tmp
1.2 When should we use them
Docstrings should generally be used only where a one-line comment just doesn't do the trick. One should also refrain from putting docstrings outside of a function or class, as without context, they are just about useless. We will go over this in more detail in How to write them
1.3 Why should we use them
As you can see, even for a relatively simple function, documenting using comments quickly makes it unpleasant and difficult to read. So, to solve this, the docstring was introduced. A docstring is simply a multi-line string, that is not assigned to anything, e.g.
"""Here be a docstring It can have multiple lines Or spaces. You can even include stuff like print("This is a docstring"), and it won't cause problems """
Using this method, our documentation of
lowerfirst() becomes far more tidy
def lowerfirst(string): """ This function takes an input string, and if the string is equal to the word "I", it will simply return that word. This function takes an input string, and if the string is equal to the word "I", it will simply return that word However, if the string is not equal to "I", it will attempt to lower the first letter by assigning it to a temporary variable, tmp, and will then append all following letters to it, returning this value once finished WARNING: This will break if the word given is only 1 letter long and not equal to I """ """ fix """ if string == "I": return string else: tmp = string.lower() for i in range(1,len(str)): tmp += i return tmp
As you can see, it considerably easier to read. However, you maybe wondering, "Well, sure, it's easier, but why do it when it's nearly identical to a comment. To answer that, you should keep reading
1.4 How to write them
While docstrings can be used as a kind of glorified comment, there is actually a lot more to them. In example, docstrings are often used by documentation generators, such as Sphinx, and DocUtils, among many others. Another function is unit tests, something that is extremely helpful when working on a large scale project. These tests take the form of the output of the interactive Python console, making it easy to not only write the test yourself, but also can be copy pasted directly from a python prompt.
def lowerfirst(string): """ This is an example unittest docstring >>> lowerfirst("I") "I" >>> lowerfirst("Hello") "hello" >>> lowerfirst("A") Traceback (most recent call last): File "<input>", line 1, in <module> IndexError: string index out of range >>> """ """ fix this markdown hates python docstrings, so I have to do this to fix it in the meantime """ if string == "I": return string else: tmp = string.lower() for i in range(1,len(str)): tmp += i return tmp
The above will be used by test systems, such as
unittests. These tools use these embedded tests to run a test, taking the user input, (sections labeled with
>>>), and execute it. If the returned value doesn't match the one below, the test will fail. This also doubles as an example of usage for other developers.
Another immensely useful functionality for documentation is the fact that docstrings use ReStructuredText, or ReST, to allow for formatting. While bearing similarities to Markdown, it can do alot more. This is where docstrings really come into their own. As well as allowing you to just write, you can also specify what arguments it takes, what it returns amongst several other sections. While easy to read in raw, tools like Sphinx, will use these for formatting.
Here are some examples:
def lowerfirst(string): """Returns the given string with the first letter lowered This is the documentation for the `lowerstring()` function, it will include the use of all common ReST sections Args: string (str): the string to process Returns: tmp (str): The string processed and lowered as necessary """ """ fix this markdown hates python docstrings, so I have to do this to fix it in the meantime """ if string == "I": return string else: tmp = string.lower() for i in range(1,len(str)): tmp += i return tmp
So, what does the above do. Well, in the given example there are several elements at play. I will explain these now
Elements of this docstring:
localstring()` The `, or backtick, is used just like in Markdown, to mark inline code highlighting
Returns:This marks the beginning of return values and type specification.
Args:This marks the beginning of argument specifications
Well, the code blocks make sense, but what purpose do the
Returns serve outside of readability. The true power of this lies in the use of Sphinx, or other documentation utilities, to generate HTML docs. The
Args header servers to give developers a list of accepted args. Optionally, one can specify the type of the argument e.g.
int. In the event one wishes to do so, this format is generally used,
<varname>[(<type>)]: <argument info>. This also applies to the
Returns section, allowing one to specify returns and their type respectively.
There are many different styles of docstrings. This guide follows the Google Docstring Styleguide. Some of the other common styles are Epytext and straight ReST. We are using the Google style of docstrings because they are the most readable, and are far easier to find documentation on
2.1 Docstring Styles
While this guide focuses on the Google Style, there are also many other styles. Here is a list of a few popular styles
amongst many others
Below is a table of common sections identifiers equivalents in each language
Note: Entries marked with a * must be inside and
Note: Types for Google Docstrings are indicated in the brackets e.g.
foo (int): a thingis a variable, with the name of
foowhich is an
intNote: Numpy style docstrings must be under the appropriate section heading. Visit the Docs for more info
So far you've seen section titles like
Returns, but there are a lot more. Below is a list of section headers, and what to use them for
Arguments: Items in this section should give a clear indication of what arguments can be passed to the function/class being documented, what type they ought to be, and what they do