Document your Python code with a docstring
Documentation is often what differentiates good code from excellent code.
In Python, docstrings allow us to effectively document our functions, classes, modules, and scripts.
Well-documented code is more readable, easier to maintain, and simpler to test – especially when working in a team or for yourself a few months later! 😋
A docstring (which is the contraction of DOCumentation STRING) is therefore a character string placed just after the declaration of a function, class, or module. It serves to explain what this block of code does, what arguments it expects, and what it returns.
Docstring syntax
The syntax of docstrings is simple, but follows precise rules to be useful and consistent.
Basic syntax
def greet(name):
"""Returns a greeting with the provided name."""
return f"Hello {name}!"
The docstring is always:
- Placed immediately after the declaration of the function (or class/module);
- Surrounded by triple quotes (
"""
..."""
) or triple single quotes ('''
...'''
); - Composed of a short phrase in imperative style (without "This function allows to...").
Incorrect example
Too often, Python developers confuse docstrings with comments.
def greet(name):
# This is a comment, not a docstring
return f"Hello {name}"
This comment will not be recognized as a docstring by help()
or documentation tools (which we'll see right after).
Even for very simple functions, a well-written docstring clarifies the developer's intention, even if the implementation is obvious.
PEP 257: the official docstring convention
Python relies on conventions to write readable code. For docstrings, the reference is PEP 257 (Python Enhancement Proposal 257 🇺🇸).
It's a convention that dictates the formal rules for writing clear and consistent docstrings in Python functions, classes, modules, and packages.
Here are the key principles to respect:
- A docstring always begins with a phrase in imperative style briefly describing the behavior;
- If necessary, a blank line separates this phrase from a more detailed description;
- For functions, we describe the parameters and the returned result;
- The docstring is placed just after the declaration, before any executable code.
This example is compliant:
def addition(a, b):
"""Adds two numbers.
Args:
a (int): first number
b (int): second number
Returns:
int: the sum of a and b
"""
return a + b
Docstring in functions
The most common form of docstring is the one we associate with functions. Well written, it serves both the users of the function and those who will maintain the code.
Example in a function
def average(grades):
"""Calculates the average of a list of grades.
Args:
grades (list of float): list of grades
Returns:
float: calculated average
"""
return sum(grades) / len(grades)
Docstring templates
When we write a docstring, it's appropriate to stick to the same structure.
In other words, we shouldn't change our way of documenting our code from one function to another.
For example, here are two well-known styles: Google Style and NumPy Style.
Google Style
def name(param1, param2):
"""Brief description.
Args:
param1 (type): description
param2 (type): description
Returns:
type: return description
"""
NumPy Style
def name(param1, param2):
"""
Brief description
Parameters
----------
param1 : type
Description
param2 : type
Description
Returns
-------
type
Description
"""
It's important to choose a single style (Google, NumPy, etc) for your entire project, to guarantee the consistency of the documentation.
Docstring in classes and methods
Classes and their methods can also be documented with docstrings.
class Dog:
"""Represents a domestic dog."""
def __init__(self, name):
"""Initializes the dog's name.
Args:
name (str): the dog's name
"""
self.name = name
def bark(self):
"""Displays a bark."""
print(f"{self.name} barks!")
Here, we document our class (Dog
), as well as its constructor (__init__
) and its method (bark
).
We therefore create three docstrings.
A method inherited from a parent class retains the original docstring, unless we redefine it. It is therefore recommended to document methods even in subclasses if their behavior differs. 😊
Docstring in modules and scripts
A docstring can also be placed at the top of a Python file (script or module). It describes the general role of the file, dependencies, or entry points.
Example of module docstring
"""
This module manages elementary mathematical operations.
Functions:
- addition(a, b)
- subtraction(a, b)
"""
def addition(a, b):
return a + b
Recommendations
To make a docstring in a module, it's important to always place it at the very top of the file, just after any declarations.
It's very useful for packages, as it will be displayed in
help(my_module)
.
Accessing docstrings
Docstrings are not only intended for human readers: they are dynamically accessible, which makes them useful in IDEs, terminals, or documentation tools.
By help()
help(print)
help(my_function)
Displays the docstring directly in the terminal or notebook.
By .__doc__
print(print.__doc__)
Returns the docstring as a character string.
In an IDE
In PyCharm, VS Code or JupyterLab:
- function hover -> automatic display;
- contextual suggestions -> docstring visible in tooltip.
Adding a docstring allows the editor to offer enriched autocompletion, which considerably improves the development experience.
Generate documentation automatically
A well-structured docstring opens the door to automatic generation of documentation in HTML, PDF or Markdown format, from the code itself. 👀
Here are some of the most popular tools for automatically generating your documentation.
Tool | Input format | Output format | Typical project |
Sphinx | reStructuredText | HTML, PDF, EPUB | Official Python documentation |
pdoc | docstrings | HTML, Markdown | Small Python projects |
mkdocstrings | Markdown | HTML (static site) | MkDocs integration |
Docstring vs comments: what are the differences?
Comments (#
) and docstrings ("""
) have distinct functions, even though they both document code.
Aspect | Comment (# ) | Docstring (""" ) |
Scope | Line or block | Function, class, module, script |
Accessibility | Invisible at runtime | Accessible via help() or .__doc__ |
Main usage | Quick logic explanation | Official description of a function, etc |
Standardization | Free | Must respect PEP-257 conventions |
Finally, docstrings do not replace comments. In fact they are complementary:
- We use docstrings for external documentation;
- Then comments to explain complex code choices.
Common errors with docstrings
Poorly writing or forgetting a docstring can harm the overall quality of the code.
Here are the common pitfalls to avoid.
Not writing a docstring
Even for simple functions, it is recommended to add at least one line quickly explaining what the function does.
Writing a too vague docstring
def process(data):
"""Does something."""
This type of docstring is useless. It's better to write nothing than to mislead.
Blindly repeating the function name
def addition(a, b):
"""Adds a and b.""" # 🚫 Too redundant
It's better to really explain the purpose of a function.
"""Returns the sum of two integers."""
Docstrings and tests
A docstring can also be used to integrate automated tests directly into the code via doctests.
def square(x):
"""Calculates the square of a number.
>>> square(3)
9
>>> square(-4)
16
"""
return x * x
To execute them:
python -m doctest my_script.py
This allows to illustrate use cases and automatically verify their validity. Perfect for pedagogy or open-source libraries.
Frequently asked questions about docstrings
What happens if I don't write a docstring?
Nothing. Your code will work, but it will be more difficult to maintain both for you and for the team that may work with you on your projects.
How can I learn Python?