Documentation#

Document your code!

Why?

“Code is more often read than written.” - Guido von Rossum

Who do you write code for?

  • users

  • developers (yourself + others, potentially)

You will go back to code you’ve written some time ago and think “What in the world was I thinking?”. If you are having trouble reading your own code, imagine what your users or other developers are experiencing when they are trying to use or contribute to your code.

Documentation is essential

It doesn’t matter how good your software is: if the documentation is not good enough, people will not use it!

Documentation versus comments#

  • Documentation: specific position (docstrings) and format -> describes use and functionality. For the users.

  • Comments: in/between code lines -> why I’m doing this? For the developers.

About comments#

Starts with a hash sign (#), next to commented code, short

def sum_numbers(*numbers):
    """Return the sum of numbers."""

    # initialize the total_sum var
    total_sum = 0

    print("numbers =", numbers)

    # TODO: check numbers type

    # calculate the sum
    for number in numbers:
        total_sum += number
    print("total_sum =", total_sum)

    return total_sum

Note

Python code is usually quite readable in itself. When this is the case, it is not necessary to add too many comments and it is much better to choose nice names and to organize the code to increase its readability and understandability.

About docstring#

A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. When configured correctly, it can help your users and yourself with your project’s documentation. Such a docstring becomes the doc special attribute of that object, and it can be printed to the console using the built-in function help():

help(str.startswith)
Help on method_descriptor:

startswith(self, prefix[, start[, end]], /) unbound builtins.str method
    Return True if the string starts with the specified prefix, False otherwise.

    prefix
      A string or a tuple of strings to try.
    start
      Optional start position. Default: start of the string.
    end
      Optional stop position. Default: end of the string.

Structure:

  • A one-line summary line

  • A blank line

  • Any further elaboration for the docstring

  • Another blank line

Syntax: triple-double quote (""")

def get_spreadsheet_cols(file_loc, print_cols=False):
    """Gets and prints the spreadsheet's header columns

    Parameters
    ----------
    file_loc : str
        The file location of the spreadsheet
    print_cols : bool, optional
        A flag used to print the columns to the
        console (default is False)

    Returns
    -------
    list
        a list of strings used that are the
        header columns
    """

    file_data = pd.read_excel(file_loc)
    col_headers = list(file_data.columns.values)

    if print_cols:
        print("\n".join(col_headers))

    return col_headers


help(get_spreadsheet_cols)
Help on function get_spreadsheet_cols in module __main__:

get_spreadsheet_cols(file_loc, print_cols=False)
    Gets and prints the spreadsheet's header columns

    Parameters
    ----------
    file_loc : str
        The file location of the spreadsheet
    print_cols : bool, optional
        A flag used to print the columns to the
        console (default is False)

    Returns
    -------
    list
        a list of strings used that are the
        header columns

How to document a project#

Readme file, docs folder (with tutorials, technical doc…), license, …

There are tools to help you create your documentation and automate doc generation from docstrings (for example Sphinx and Read The Docs).

Typing annotations for documentation#

Modern Python can include typing annotations. These annotations can be used by third party tools such as type checkers, IDEs, linters. They can also be useful for the perspective of the documentation. For example, one can write:

def compute_quantities(a: float, b: float) -> dict[str, float]:
    return {"product": a * b, "sum": a + b}