Learn How to Write Multi-line Documentation in Python: Absolute Beginners Tutorial

When a Python function grows beyond a few lines, a short comment above the def line is not enough to explain what it does, what it accepts, and what it returns. Python solves this with docstrings -- string literals placed directly inside a definition that the interpreter stores, that the built-in help() function displays, and that documentation generators like Sphinx can turn into full reference pages. This tutorial walks you through multi-line docstrings from first principles so you can start writing clear, useful documentation in your own code today.

If you have ever opened someone else's Python project and immediately understood what each function did without reading through the implementation, you were reading good docstrings. If you have ever stared at a function signature for minutes trying to figure out what the parameters expected, you were looking at code that lacked them. Multi-line docstrings sit at the heart of this difference, and Python gives them first-class treatment that no other common language matches quite as directly.

What Is a Docstring and Why Does It Matter?

A docstring is a string literal that appears as the very first statement inside a module, function, class, or method definition. Python's interpreter recognizes that placement and automatically assigns the string to the object's __doc__ attribute. That single rule is what separates a docstring from every other string or comment in your code.

Regular comments begin with the # character and are stripped out during compilation. They exist only in the source file. A docstring, on the other hand, is preserved at runtime. You can print it, pass it to help(), and hand it off to documentation generation tools. This means the documentation lives with the code and travels wherever the code goes.

python
def calculate_area(radius):
    """Calculate the area of a circle given its radius."""
    import math
    return math.pi * radius ** 2

# Access the docstring at runtime
print(calculate_area.__doc__)
# Output: Calculate the area of a circle given its radius.

help(calculate_area)
# Displays the docstring in an interactive viewer

The example above uses a one-line docstring because the explanation fits on a single line. That works when the function is simple. When a function accepts multiple parameters, raises exceptions, or returns complex data, a single sentence is not enough. That is where multi-line docstrings come in.

Note

PEP 257 is the Python Enhancement Proposal that standardizes docstring conventions. It is not enforced by the interpreter -- your code will run regardless -- but tools like Sphinx, PyCharm, and Ruff all rely on these conventions. Following PEP 257 means your documentation works seamlessly with the rest of the Python ecosystem.

The distinction between a comment and a docstring matters for beginners because it affects how you think about documentation. Comments explain why code works the way it does. Docstrings explain what code does and how to use it. Both are valuable, and they serve different audiences.

Pro Tip

A quick way to check whether your docstring is working: open a Python shell, import your function, and type help(your_function). If nothing appears, the string is not in the __doc__ position. The most common mistake is placing a line of code before the string, which causes Python to skip it.

python
# This is WRONG -- the docstring is not the first statement
def bad_example(x):
    result = x * 2
    """Multiply x by two."""   # Python ignores this as a docstring
    return result

print(bad_example.__doc__)
# Output: None
code builder click a token to place it

Build a correct one-line docstring inside a function definition by clicking the tokens in order:

your code will appear here...
: return name def """Return a greeting for the given name.""" ( # Return a greeting greet )

Anatomy of a Multi-line Docstring

A multi-line docstring has a specific structure defined by PEP 257. It begins with a summary line on the same line as the opening triple quotes. That summary should fit on one line and describe what the function does in a concise sentence. After the summary comes a blank line, followed by a more detailed description. The closing triple quotes go on a line by themselves.

python
def connect_to_database(host, port, timeout=30):
    """Establish a connection to the specified database server.

    Attempts to connect using TCP on the given host and port.
    If the connection is not established within the timeout
    period, a ConnectionError is raised.

    Args:
        host (str): The hostname or IP address of the server.
        port (int): The port number to connect on.
        timeout (int): Seconds to wait before giving up.
            Defaults to 30.

    Returns:
        Connection: An active database connection object.

    Raises:
        ConnectionError: If the server cannot be reached
            within the timeout period.
    """
    # implementation here
    pass

Every part of that structure serves a purpose. The summary line on the first line allows automatic indexing tools to extract a short description without parsing the entire docstring. The blank line signals to parsers that the summary is complete. The extended description provides the detail that a developer needs when the summary alone is not enough.

PEP 257 also requires that the indentation of every line in the docstring matches the indentation of the opening quotes. Documentation tools strip a uniform amount of leading whitespace from the second and subsequent lines, using the minimum indentation of all non-blank lines after the first line as the baseline.

Where Docstrings Belong

You can place docstrings in four locations: modules (at the very top of a .py file), classes (directly after the class line), functions (directly after the def line), and methods (same as functions, but inside a class). Each location has slightly different conventions for what to include.

Placement
First statement in the .py file, before imports
What to Include
A summary of the module's purpose, plus a list of the classes, functions, and exceptions it exports
Placement
First statement after the class header line
What to Include
A summary of the class behavior, its public methods, and instance variables. PEP 257 requires a blank line after the docstring before the first method.
Placement
First statement after the def line
What to Include
A summary of behavior, documentation of arguments, return values, side effects, exceptions raised, and any restrictions on when it can be called
python
"""File utilities for reading and writing CSV data.

This module provides helper functions for loading CSV files
into Python data structures and writing them back to disk.

Functions:
    read_csv -- Load a CSV file and return a list of dicts.
    write_csv -- Write a list of dicts to a CSV file.
"""

import csv


class DataLoader:
    """Load and validate structured data from external sources.

    Supports CSV and JSON input formats. Each instance is bound
    to a single source file specified at construction time.

    Attributes:
        filepath (str): Path to the source file.
        encoding (str): Character encoding used when reading.
    """

    def __init__(self, filepath, encoding="utf-8"):
        """Initialize the DataLoader with a file path.

        Args:
            filepath (str): Path to the data file.
            encoding (str): File encoding. Defaults to utf-8.
        """
        self.filepath = filepath
        self.encoding = encoding
spot the bug click the line that contains the bug

This function is supposed to have a valid docstring, but something is wrong. Click the line you think causes the problem, then hit check.

1 def parse_config(path):
2 config = {}
3 """Parse a configuration file and return a dict."""
4 with open(path) as f:
5 for line in f:
6 key, val = line.strip().split("=")
The fix: Move the docstring to line 2 and push config = {} below it. A docstring must be the first statement inside the function. Because config = {} comes first on line 2, Python treats the triple-quoted string on line 3 as an ordinary expression, not a docstring. Calling parse_config.__doc__ would return None.

Three Popular Docstring Formatting Styles

PEP 257 defines the structural rules for docstrings -- where they go, how to separate the summary from the body -- but it does not prescribe how to format parameter lists, return values, or exception documentation within the body. Three community conventions have emerged to fill that gap, and each has its own strengths.

reStructuredText (reST) Style

This is the native format for Sphinx, the documentation generator used by the Python standard library and many open-source projects. It uses field-list directives like :param:, :type:, :returns:, and :raises:. PyCharm generates reST-style stubs by default when you type triple quotes after a def line and press Enter.

python
def send_email(recipient, subject, body):
    """Send an email message to a single recipient.

    Connects to the configured SMTP server and delivers
    the message. The connection is closed automatically
    after delivery.

    :param recipient: Email address of the recipient.
    :type recipient: str
    :param subject: Subject line of the email.
    :type subject: str
    :param body: Plain-text body content.
    :type body: str
    :returns: True if the email was accepted by the server.
    :rtype: bool
    :raises smtplib.SMTPException: If delivery fails.
    """
    pass

Google Style

Google style uses plain section headers followed by indented content. It tends to be the most readable in source code, especially for shorter docstrings. Sphinx can parse it through the sphinx.ext.napoleon extension.

python
def send_email(recipient, subject, body):
    """Send an email message to a single recipient.

    Connects to the configured SMTP server and delivers
    the message. The connection is closed automatically
    after delivery.

    Args:
        recipient (str): Email address of the recipient.
        subject (str): Subject line of the email.
        body (str): Plain-text body content.

    Returns:
        bool: True if the email was accepted by the server.

    Raises:
        smtplib.SMTPException: If delivery fails.
    """
    pass

NumPy Style

NumPy style uses section headers underlined with dashes. It requires more vertical space but is easier to scan when docstrings contain long parameter descriptions. Libraries like NumPy, pandas, and SciPy follow this convention, and Sphinx supports it through the same napoleon extension.

python
def send_email(recipient, subject, body):
    """Send an email message to a single recipient.

    Connects to the configured SMTP server and delivers
    the message. The connection is closed automatically
    after delivery.

    Parameters
    ----------
    recipient : str
        Email address of the recipient.
    subject : str
        Subject line of the email.
    body : str
        Plain-text body content.

    Returns
    -------
    bool
        True if the email was accepted by the server.

    Raises
    ------
    smtplib.SMTPException
        If delivery fails.
    """
    pass
Pro Tip

The most important rule is consistency. Pick one style and use it across your entire project. Mixing styles confuses both human readers and automated documentation tools. If you are starting fresh and want the most readable option for short-to-medium functions, Google style is a strong default.

Side-by-side comparison of the three main Python docstring formatting conventions: reStructuredText, Google, and NumPy.

How to Write a Multi-line Docstring in Python

Follow these three steps to write a PEP 257 compliant multi-line docstring for any Python function. The same pattern applies to classes, methods, and modules.

  1. Define your function and open the docstring

    Write the def line for your function. On the next indented line, open a set of triple double quotes and write a one-line summary on that same line. The summary should describe what the function does, written as a command (for example, "Calculate the area" rather than "This function calculates the area"). End the summary with a period.

  2. Add a blank line and write the detailed description

    Leave one blank line after the summary. Then write the extended description, which can include documentation of parameters, return values, exceptions raised, usage notes, and examples. Use one of the three formatting styles (reStructuredText, Google, or NumPy) consistently. Indent every line of the body to match the indentation of the opening quotes.

  3. Close the docstring on its own line

    After the last line of the description, place the closing triple double quotes on a new line by themselves, aligned with the opening quotes. If the docstring belongs to a class, add a blank line after the closing quotes before the first method definition. For functions, no extra blank line is required.

"A universal convention supplies all of maintainability, clarity, consistency." — PEP 257, Python Software Foundation

Python Learning Summary Points

  1. A docstring is a string literal placed as the first statement inside a module, class, function, or method. Python stores it in the __doc__ attribute and makes it available to help() and documentation generators.
  2. Multi-line docstrings follow a specific PEP 257 structure: a one-line summary, a blank line, then a detailed description, with the closing triple quotes on their own line.
  3. Three formatting styles are widely used for structuring parameter and return documentation: reStructuredText (Sphinx native), Google style (concise and readable), and NumPy style (common in scientific libraries). Consistency within a project matters more than which style you choose.
  4. The most common beginner mistake is placing code before the docstring, which causes Python to treat the string as an ordinary expression rather than documentation. Always make the docstring the very first statement.
  5. Use help() and __doc__ to verify your docstrings at runtime. If the output is None, the string is not in the correct position.

Writing thorough multi-line docstrings takes a few extra seconds per function, but the payoff compounds every time someone (including your future self) needs to understand what a piece of code does without reading through the implementation. Start with simple functions, pick a formatting style, and build the habit early. Your codebase will be better for it.

check your understanding question 1 of N

║ Each .faq-item needs a question in .faq-trigger and an ║ ║ answer in .faq-answer. Aim for 8–16 questions per article. ║ ║ Phrase questions as "What is...", "How does...", etc. ║ ║ Must match the FAQPage JSON-LD block question-for-question. ║ ╚══════════════════════════════════════════════════════════════╝ -->

Frequently Asked Questions

A multi-line docstring is a string literal enclosed in triple quotes that spans multiple lines. It serves as the first statement inside a function, class, method, or module to document what that code does. Python stores the docstring in the object's __doc__ attribute so it can be accessed at runtime.

Comments use the # symbol and are ignored by the interpreter entirely. Docstrings are string literals placed as the first statement in a definition and are stored in the __doc__ attribute, making them accessible at runtime through help() and documentation tools. Comments explain implementation details while docstrings explain purpose and usage.

PEP 257 recommends using triple double quotes for all docstrings. While triple single quotes are syntactically valid, triple double quotes are the established convention across the Python community and recognized by documentation generation tools.

You can access a docstring using the __doc__ attribute on any object that has one. For example, print(my_function.__doc__) prints the docstring of my_function. You can also use the built-in help() function, which displays the docstring in an interactive help viewer.

PEP 257 is the Python Enhancement Proposal that documents the conventions for writing docstrings. It standardizes what docstrings should contain and how they should be structured, including rules for one-line and multi-line formats. Following PEP 257 helps documentation tools parse your code correctly and keeps your documentation consistent.

The three main styles are reStructuredText (reST), Google style, and NumPy style. reStructuredText uses :param: and :returns: directives and is Sphinx's native format. Google style uses indented sections like Args and Returns. NumPy style uses section headers underlined with dashes and is common in scientific computing libraries.

If a string literal is not the first statement inside a function, class, or module definition, Python does not assign it to the __doc__ attribute. It becomes an ordinary string expression that has no effect. The help() function will not display it, and documentation generators will not detect it.

Yes. PEP 257 states that multi-line docstrings should begin with a one-line summary, followed by a blank line, followed by the more detailed description. The blank line separates the summary from the body and allows automatic indexing tools to extract the summary independently.

Python does not natively assign a __doc__ attribute to variables. However, PEP 257 mentions attribute docstrings, which are string literals placed immediately after a simple assignment at the top level of a module, class, or __init__ method. Some documentation tools like Sphinx can extract these attribute docstrings.

Google style is often recommended for beginners because it uses plain section headers and indentation rather than special markup syntax. It is easy to read in source code and is supported by Sphinx through the napoleon extension. The key principle is to pick one style and use it consistently across your project.