5 Best Practices for Writing Python Docstrings

Rate this post

πŸ’‘ Problem Formulation: Clear and comprehensive documentation is vital in Python development for understanding what a piece of code does, its inputs, outputs, and how to correctly use it. This article tackles the challenge of effectively using Python docstrings to convey this information, following Pythonic conventions. For instance, if the input is a function add(a, b), the desired output would be a well-documented code explaining the functionality, parameters, and the return value of add.

Method 1: Basic Docstrings

The simplest method of documenting Python code is to use basic docstrings. A docstring is a literal string placed right after a function, method, class, or module definition that explains its purpose. They should be concise yet informative. Docstrings can be accessed by the built-in help() function, making them instantly useful for any developer working with your code.

Here’s an example:

def add(a, b):
    """
    Add two numbers and return the sum.
    Parameters:
    a (int): First number
    b (int): Second number
    
    Returns:
    int: Sum of a and b
    """
    return a + b

help(add)

Output:

Help on function add in module __main__:

add(a, b)
    Add two numbers and return the sum.
    Parameters:
    a (int): First number
    b (int): Second number
    
    Returns:
    int: Sum of a and b

This code snippet defines a function add that sums two numbers. The docstring, enclosed in triple quotes, provides a clear and concise explanation of the function’s purpose, parameters, and return type which helps any developer to quickly understand and utilize the function.

Method 2: Sphinx-Compatible Docstrings

Sphinx is a tool that generates beautiful documentation for Python projects, and it uses reStructuredText as its markup language. Writing docstrings that are compatible with Sphinx can allow you to create robust documentation websites for your code. Sphinx-compatible docstrings often use special directive blocks such as :param and :return: to describe function parameters and return values.

Here’s an example:

def multiply(a, b):
    """
    Multiply two numbers together.
    
    :param a: First number
    :type a: int
    :param b: Second number
    :type b: int
    :return: Product of a and b
    :rtype: int
    """
    return a * b

help(multiply)

Output:

Help on function multiply in module __main__:

multiply(a, b)
    Multiply two numbers together.
    
    :param a: First number
    :type a: int
    :param b: Second number
    :type b: int
    :return: Product of a and b
    :rtype: int

This code snippet demonstrates how to write a Sphinx-friendly docstring for the multiply function. The docstring uses Sphinx-specific directives to provide detailed information about the function’s parameters and return value. This format is particularly useful when you’re using Sphinx to generate your documentation.

Method 3: Google Style Docstrings

Google style docstrings are a popular convention that is considered highly readable. They use a simple and clean layout, making heavy use of whitespace to separate sections. Google style docstrings are supported by many tools for generating documentation, such as Sphinx with the napoleon plugin.

Here’s an example:

def subtract(a, b):
    """
    Subtract the second number from the first and return the difference.

    Args:
        a (int): First number
        b (int): Number to subtract from the first

    Returns:
        int: The difference between a and b
    """
    return a - b

help(subtract)

Output:

Help on function subtract in module __main__:

subtract(a, b)
    Subtract the second number from the first and return the difference.

    Args:
        a (int): First number
        b (int): Number to subtract from the first

    Returns:
        int: The difference between a and b

This example illustrates the use of a Google style docstring for the function subtract. It includes sections for arguments (Args) and the return value (Returns), with a human-readable description. Its straightforward style makes it an appealing choice for many developers.

Method 4: Numpydoc Style Docstrings

The numpydoc style is a format for docstrings that was created for the NumPy project but has gained popularity among other scientific and analytical Python projects. The numpydoc format is quite structured and provides a clear convention for mentioning parameters, return values, and other information.

Here’s an example:

def divide(a, b):
    """
    Divide the first number by the second and return the quotient.

    Parameters
    ----------
    a : int
        Numerator.
    b : int
        Denominator.

    Returns
    -------
    int
        The quotient of a and b.
    """
    return a / b

help(divide)

Output:

Help on function divide in module __main__:

divide(a, b)
    Divide the first number by the second and return the quotient.

    Parameters
    ----------
    a : int
        Numerator.
    b : int
        Denominator.

    Returns
    -------
    int
        The quotient of a and b.

The divide function is documented using the numpydoc style, which lends a scientific paper-like format that some developers find very appealing. It includes clear sections and subsections, and it’s particularly suited for scientific libraries.

Bonus One-Liner Method 5: Inline Docstrings

Sometimes, functions are simple enough that a one-liner docstring would suffice. This should only be used when the function is extremely straightforward and performs a single, uncomplicated task. One-liners still follow the PEP 257 – Docstring Conventions which suggest a summary line in quotation marks located right below the function’s signature.

Here’s an example:

def greet(name):
    "Return a simple greeting message."
    return f"Hello, {name}!"

help(greet)

Output:

Help on function greet in module __main__:

greet(name)
    Return a simple greeting message.

The greet function showcases the use of a one-liner docstring that is adequate for very simple functions. It’s clear, concise, and directly tells what the function does without detailing parameters or return values.

Summary/Discussion

  • Method 1: Basic Docstrings. Easy to write and understand. Good for small-scale projects and scripts. May lack details for complex functions.
  • Method 2: Sphinx-Compatible Docstrings. Excellent for generating documentation with Sphinx. Requires additional effort to adhere to the markup. Not necessary for simple scripts.
  • Method 3: Google Style Docstrings. Highly readable and standardized. Supported by various tools for documentation generation. Slightly more verbose than basic docstrings.
  • Method 4: Numpydoc Style Docstrings. Provides a high level of detail. Ideal for scientific and analytical communities. Can be too structured for simple projects.
  • Bonus Method 5: Inline Docstrings. Quick and suitable for very simple functions. Not enough for functions requiring detailed explanations.