A docstring is the string literal that comes first in a module, class or function, and it is the one piece of documentation that travels with the code everywhere it goes. Written well, it tells a colleague what a function does, what it expects and what it hands back - without them opening the source at all.
What is a docstring, and when does Python read it?
If the first statement in a module, class or function body is a string literal, Python stores it as that object's __doc__ attribute. That is the whole mechanism. There is no special syntax, no decorator and no import required - and because the literal is never evaluated as code, it costs nothing at runtime beyond a few bytes of memory.
def celsius_to_fahrenheit(celsius: float) -> float:
"""Convert a Celsius temperature to Fahrenheit.
Args:
celsius: Temperature in degrees Celsius.
Returns:
The equivalent temperature in degrees Fahrenheit.
"""
return celsius * 9 / 5 + 32
print(celsius_to_fahrenheit(100))
print(celsius_to_fahrenheit.__doc__.splitlines()[0])
The one-line summary at the top is the part that matters most, because it is what appears in help() listings, in IDE tooltips and in generated reference documentation. Write it as a full sentence that starts with a verb - "Convert", not "Converts" or "A function that converts" - and end it with a period. Readers scan that first line far more often than they read the body.
What belongs in a docstring, and what does not?
A useful docstring answers four questions in this order: what the thing does, what it needs, what it returns, and what it might raise. Everything else belongs elsewhere.
class ShoppingCart:
"""A cart that holds products and their quantities.
Attributes:
items: Mapping of product name to quantity in the cart.
"""
def __init__(self) -> None:
"""Create an empty cart."""
self.items: dict[str, int] = {}
def add(self, product: str, qty: int = 1) -> None:
"""Add qty of a product to the cart.
Args:
product: Name of the product to add.
qty: How many to add. Must be positive.
Raises:
ValueError: If qty is not positive.
"""
if qty <= 0:
raise ValueError("qty must be positive")
self.items[product] = self.items.get(product, 0) + qty
cart = ShoppingCart()
cart.add("mug", 2)
print(cart.items)
print(ShoppingCart.__doc__.splitlines()[0])
print(ShoppingCart.add.__doc__.splitlines()[0])
Notice what is missing. The docstring does not repeat the signature, does not narrate the assignment line by line, and does not apologise. It also does not go stale silently: when a parameter is renamed, the type checker flags the mismatch and the docstring is the thing you remember to update in the same breath.
Two habits are worth adopting early. Document the Raises section, because the exception type is the part of an interface people cannot guess. And keep one-line docstrings genuinely one line - a multi-line docstring for a trivial function signals that the function has more behaviour than its name suggests.
Which docstring style should you use?
Three conventions dominate, and all of them are accepted by every documentation generator. Pick one for the project and stay with it, because mixed styles are worse than any single style.
| Style | Sections look like | Best for |
|---|---|---|
| Google style | Args:, Returns:, Raises: | General projects; the most widely recognised and easy to read in plain text. |
| NumPy style | Parameters, Returns with indented type blocks | Scientific and numerical libraries where the parameter list is long and typed. |
| reStructuredText | :param x:, :returns: | Projects already documented with Sphinx; older codebases. |
A short function does not need any of them. "Return the total price including tax." is a complete docstring for a two-line function, and adding an empty Args: section to it is noise.
Readable code and good docstrings are the same investment seen from two sides. A docstring forces you to state the contract before you write the body, and a contract you cannot state in two lines is usually a contract you have not thought about. Names follow the same logic: cart_total tells a reader more than calc, and no amount of documentation rescues a name that hides its meaning.
When should you write a comment instead?
The rule of thumb: a docstring describes what a thing is and does; a comment explains something a reader of that code could not work out on their own. A comment that restates the code is worse than no comment, because it adds something to maintain and teaches nothing.
subtotal = 19.99
discount = 2.00
# BAD - the comment says what the next line says
# add the discount to the total
total = subtotal + discount
print(total)
items = list(range(150))
# GOOD - the comment explains a rule the code cannot show
# The payments API rejects batches larger than 100 items.
batch = min(len(items), 100)
print(batch)
Comments should also explain decisions, not mechanics: why a retry limit is three, why a cache is invalidated after thirty seconds, why an unusual spelling is kept for compatibility with an external system. If the "why" is not in the code and not in the docstring, it disappears when the code changes - and the next person is left guessing.
How do you read docstrings without leaving the terminal?
Three tools cover almost every case. help() prints the full documentation for an object, inspect.getdoc() returns it as a string, and python -m pydoc generates browsable documentation for a whole module.
import inspect
class Base:
"""Base class for the account hierarchy."""
class Savings(Base):
pass
class Premium(Savings):
"""An account that earns interest."""
def greet(name: str, excited: bool = False) -> str:
"""Return a greeting for name."""
return f"Hi {name}{'!' if excited else ''}"
print(inspect.getdoc(Savings))
print(Savings.__doc__)
print(inspect.signature(greet))
print(greet.__doc__)
That third line of output is the one to notice: inspect.getdoc(Savings) returns "Base class for the account hierarchy." while Savings.__doc__ is None. getdoc looks up the class hierarchy for an inherited docstring, which is why it is the better choice when you are reading documentation programmatically. Use it whenever you cannot be sure the object has its own text.
# browse a module's documentation in the terminal
python -m pydoc mymodule
# same thing, but with the source shown
python -m pydoc -s mymodule
Next steps
- Every module, class and public function gets a docstring with a one-line summary that starts with a verb.
- Document parameters, return values and raised exceptions - the parts a caller has to get right.
- Choose one section style per project and apply it consistently.
- Keep comments for reasoning and constraints, never for narration.
- Read your own docstring through
help()once a month; if it reads oddly, the function probably wants renaming.
Try it yourself: Pick the longest function in one of your own scripts. Delete its comments and docstring, then write them again from the caller's point of view: what goes in, what comes out, what can go wrong. Time yourself. If the rewrite took more than two minutes, that is a sign the function's interface is doing too much - splitting it into two smaller functions usually makes the documentation trivial to write.