How to write a docstring in Python
Learn how to write Python docstrings. This guide covers different methods, tips, real-world examples, and how to debug common errors.
.avif)
Python docstrings are essential for clear documentation. They explain what your code does, which helps you and others understand and maintain functions, modules, and classes more effectively.
Here, you'll learn essential techniques and tips for writing powerful docstrings. We'll explore real-world applications and provide debugging advice to help you improve your code's overall quality and readability.
Writing basic docstrings with triple quotes
def greet(name):
"""This function greets the person passed in as a parameter."""
return f"Hello, {name}!"
print(greet.__doc__)--OUTPUT--This function greets the person passed in as a parameter.
In the greet function, the docstring is enclosed in triple quotes right below the function signature. This specific placement is crucial because it tells Python to attach the string to the function's special __doc__ attribute. It’s more than a simple comment; it becomes a piece of metadata tied directly to the function object.
When you call print(greet.__doc__), you're accessing this built-in attribute. This is the underlying mechanism that allows development tools and the native help() function to automatically pull and display your documentation, making your code much easier for others to understand and use.
Common docstring styles
Beyond the basic triple-quote docstring, several established conventions like the Google, reST, and NumPy styles provide more structure for documenting complex functions.
Using Google-style docstrings with Args and Returns
def divide(a, b):
"""Divides two numbers and returns the result.
Args:
a (int): The dividend
b (int): The divisor
Returns:
float: The quotient of a divided by b
"""
return a / b
print(divide.__doc__)--OUTPUT--Divides two numbers and returns the result.
Args:
a (int): The dividend
b (int): The divisor
Returns:
float: The quotient of a divided by b
The Google style adds structure, making your docstrings much clearer. After the initial summary, it uses specific sections to organize information.
Args:This section lists each parameter on a new line, specifying its expected data type—like(int)—and a short description of its role.Returns:Here, you describe what the function gives back, including its type, such asfloat.
This format isn't just for humans; it allows automated tools to understand and display your function's documentation effectively.
Writing reStructuredText (reST) style docstrings with :param:
def multiply(a, b):
"""Multiply two numbers and return the result.
: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
print(multiply.__doc__)--OUTPUT--Multiply two numbers and return the result.
:param a: First number
:type a: int
:param b: Second number
:type b: int
:return: Product of a and b
:rtype: int
The reStructuredText (reST) style is another popular convention, particularly favored by documentation generators like Sphinx. It uses explicit tags to define each part of the function's contract.
- Use
:param:and:type:to describe each parameter and its data type on separate lines. - Similarly,
:return:and:rtype:detail the function’s output and its type.
While this format is more verbose, its highly structured nature makes it straightforward for automated tools to parse.
Implementing NumPy-style docstrings with Parameters section
def subtract(a, b):
"""Subtract b from a and return result
Parameters
----------
a : int
The minuend
b : int
The subtrahend
Returns
-------
int
Difference between a and b
"""
return a - b
print(subtract.__doc__)--OUTPUT--Subtract b from a and return result
Parameters
----------
a : int
The minuend
b : int
The subtrahend
Returns
-------
int
Difference between a and b
The NumPy style, popular in scientific computing libraries, is prized for its exceptional readability. It organizes documentation into distinct, underlined sections.
- The
Parameterssection details each input. Each parameter, likea : int, gets its own line, followed by an indented description below it. - The
Returnssection follows a similar pattern, first specifying the output's data type and then providing an indented description.
This clean, organized format makes it easy to quickly understand a function's purpose and requirements.
Advanced docstring techniques
Beyond functions, docstrings also populate the __doc__ attribute for classes and modules, which the help() function uses to display documentation.
Using docstrings with the __doc__ attribute in classes
class Calculator:
"""A simple calculator class with basic arithmetic operations."""
def add(self, a, b):
"""Add two numbers and return the sum."""
return a + b
print(Calculator.__doc__)
print(Calculator.add.__doc__)--OUTPUT--A simple calculator class with basic arithmetic operations.
Add two numbers and return the sum.
Docstrings aren't just for functions; they're equally important for classes. In the Calculator example, the docstring placed directly under the class definition explains its overall purpose. Each method within the class, like add, also has its own docstring to describe its specific job.
Calculator.__doc__accesses the class's documentation.Calculator.add.__doc__retrieves the docstring for theaddmethod.
This separation helps document both the high-level component and its individual parts clearly.
Adding docstrings with the help() function
def power(base, exponent=2):
"""Calculate power of a number.
Args:
base: The base number
exponent: The exponent value (default: 2)
Returns:
The result of base raised to exponent
"""
return base ** exponent
help(power)--OUTPUT--Help on function power in module __main__:
power(base, exponent=2)
Calculate power of a number.
Args:
base: The base number
exponent: The exponent value (default: 2)
Returns:
The result of base raised to exponent
The built-in help() function is a powerful tool for accessing documentation directly in your Python session. When you pass a function like power to it, Python automatically finds and displays its docstring in a clean, readable format.
- It presents the function's signature, like
power(base, exponent=2), so you know what arguments it accepts. - It also neatly formats the entire docstring, including the
ArgsandReturnssections.
This lets you quickly understand how to use a function without digging through the source code.
Creating module-level docstrings with __doc__
"""This module contains utility functions for mathematical operations.
It provides functions for basic arithmetic as well as more complex operations.
"""
import sys
print(sys.modules[__name__].__doc__)--OUTPUT--This module contains utility functions for mathematical operations.
It provides functions for basic arithmetic as well as more complex operations.
A docstring at the very top of a Python file documents the entire module. It’s your chance to give a high-level summary of the file's purpose and what it contains, like a collection of related functions.
- This top-level docstring is automatically attached to the module's special
__doc__attribute. - The code
sys.modules[__name__].__doc__programmatically finds the current module and prints its documentation, making it accessible to you and other development tools.
Move faster with Replit
Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. You can focus on what you're building, not on configuring your environment.
Mastering individual techniques like docstrings is a great start. Agent 4 helps you take the next step, moving from writing functions to building complete applications. It takes your idea and handles the entire development process—from writing code and connecting to APIs to testing and deployment—all from a simple description.
Instead of piecing together functions like add or power, you can describe the complete tool you want to build, and Agent will construct it:
- A web-based loan calculator that uses the principles behind the
powerfunction to compute compound interest and amortization schedules. - An e-commerce pricing tool that applies discounts using subtraction and calculates sales tax with multiplication.
- A scientific conversion utility that uses division and multiplication to instantly switch between metric and imperial units.
Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
Even with established styles, you can run into common issues like inconsistent indentation, buggy examples, and mismatched function signatures.
Fixing inconsistent indentation in Google-style docstrings
In Google-style docstrings, indentation is key. The descriptions for your parameters under the Args: section must be indented correctly; otherwise, documentation generators might not parse them correctly. This can lead to poorly formatted or even missing documentation for your function's arguments.
To fix this, ensure the description text is consistently indented under the parameter it describes. This simple alignment maintains the structure that automated tools rely on to render your documentation clearly and accurately.
Correcting bugs in doctest examples
The doctest module lets you embed runnable code examples directly within your docstrings, serving as both documentation and tests. However, a tiny error in your example code or its expected output will cause the test to fail, signaling a bug in your documentation.
These failures happen when the example's output in the docstring doesn't exactly match what the code actually produces. Carefully review your examples to ensure they are precise, as this confirms your code works as described and that your documentation is reliable.
Ensuring docstrings match function signatures
As code evolves, it's easy for a function's signature to change while its docstring gets left behind. This creates misleading documentation, where the docstring describes parameters or return values that no longer exist or have been renamed.
This discrepancy can confuse developers and lead to incorrect usage of the function. Always update the docstring immediately after you modify a function's signature. Pay close attention when you:
- Rename, add, or remove a parameter.
- Change a parameter's default value.
- Alter the data type or structure of what the function returns.
Fixing inconsistent indentation in Google-style docstrings
With Google-style docstrings, proper indentation is non-negotiable. If the description for a parameter isn't aligned correctly, documentation generators can fail. The following calculate_discount function shows a common example of this subtle but problematic indentation error.
def calculate_discount(price, discount_rate):
"""Calculate the discounted price.
Args:
price (float): The original price
discount_rate (float): The discount rate as a decimal
Returns:
float: The price after applying the discount
"""
return price * (1 - discount_rate)
Here, the Args: and Returns: sections lack indentation, causing documentation generators to misinterpret the docstring and produce broken formatting. The corrected code below shows how to fix the alignment for proper parsing.
def calculate_discount(price, discount_rate):
"""Calculate the discounted price.
Args:
price (float): The original price
discount_rate (float): The discount rate as a decimal
Returns:
float: The price after applying the discount
"""
return price * (1 - discount_rate)
The fix is to indent the Args: and Returns: sections so they align with the main description. This seemingly minor adjustment is critical because automated tools rely on that whitespace to understand the docstring's structure. Without proper alignment, parsers can't distinguish parameters from the summary, leading to broken or unreadable documentation. It's a small detail that makes a big difference in how your code is presented and understood by others.
Correcting bugs in doctest examples
The doctest module runs examples in your docstrings to verify your code works as documented. A small mismatch between the expected output and the actual result will cause a test failure, indicating a bug in either the code or the documentation.
In the celsius_to_fahrenheit function below, one of the examples has an incorrect output. This causes the doctest to fail, even though the function's conversion logic is perfectly fine. See if you can spot the error.
def celsius_to_fahrenheit(celsius):
"""Convert Celsius to Fahrenheit.
>>> celsius_to_fahrenheit(0)
32.0
>>> celsius_to_fahrenheit(100)
212.0
>>> celsius_to_fahrenheit(25)
75.0
"""
return (celsius * 9/5) + 32
The test fails because the example for celsius_to_fahrenheit(25) incorrectly expects an output of 75.0. The function's logic is sound, but the documented result is wrong, causing the mismatch. The corrected version below shows the fix.
def celsius_to_fahrenheit(celsius):
"""Convert Celsius to Fahrenheit.
>>> celsius_to_fahrenheit(0)
32.0
>>> celsius_to_fahrenheit(100)
212.0
>>> celsius_to_fahrenheit(25)
77.0
"""
return (celsius * 9/5) + 32
The test for celsius_to_fahrenheit failed because its docstring contained a faulty example. The documentation claimed that converting 25 degrees Celsius would result in 75.0, but the function correctly returns 77.0. By updating the expected output in the docstring, the test now passes. This highlights how doctest helps you catch discrepancies between your code and its documentation, ensuring your examples are always accurate and reliable.
Ensuring docstrings match function signatures
When you refactor code, it's easy to forget to update the docstring. This creates a mismatch where the documentation no longer reflects the function's actual parameters or behavior, leading to confusion and bugs for anyone trying to use it.
The send_email function below is a perfect example of this issue. Its signature was changed, but the docstring wasn't updated to match, creating a discrepancy that can easily trip up other developers.
def send_email(recipient, subject, body):
"""Send an email to a recipient.
Args:
recipient (str): Email address of the recipient
subject (str): Subject line of the email
Returns:
bool: True if the email was sent successfully
"""
# Email sending logic here
return True
The function signature for send_email clearly includes a body parameter, but the docstring's Args section is missing it entirely. This creates a disconnect that can easily lead to implementation errors. The corrected code below resolves this discrepancy.
def send_email(recipient, subject, body):
"""Send an email to a recipient.
Args:
recipient (str): Email address of the recipient
subject (str): Subject line of the email
body (str): Content of the email
Returns:
bool: True if the email was sent successfully
"""
# Email sending logic here
return True
The send_email function's docstring was out of sync with its signature, missing the body parameter in the Args section. The fix was simple: adding the missing parameter to make the documentation accurate. This kind of mismatch is common during refactoring, so it's crucial to update your docstrings whenever you change a function's parameters to keep your documentation reliable.
Real-world applications
With a solid grasp of docstring fundamentals and error fixing, you can now leverage them for powerful applications like automated testing and API documentation.
Using docstrings with doctest for automated testing
The doctest module transforms your documentation into an automated testing tool by running the code examples you embed directly in your docstrings.
def is_palindrome(text):
"""Check if a string is a palindrome.
>>> is_palindrome('radar')
True
>>> is_palindrome('hello')
False
"""
text = text.lower().replace(' ', '')
return text == text[::-1]
import doctest
doctest.testmod()
In the is_palindrome function, the docstring includes runnable examples like >>> is_palindrome('radar'). These aren't just for show; they define the function's expected behavior and serve as live tests.
When doctest.testmod() is called, it automatically finds and executes these examples. It then compares the actual output against the documented result, like True or False. This process verifies that your code works exactly as your documentation claims, making your docstrings a reliable source of truth and a simple testing framework rolled into one.
Creating API documentation with docstrings and Sphinx
You can use tools like Sphinx to transform your reStructuredText (reST) docstrings into comprehensive API documentation, complete with advanced formatting like mathematical equations.
def calculate_area(radius):
"""Calculate the area of a circle.
:param radius: The radius of the circle
:type radius: float
:return: The area of the circle
:rtype: float
.. math::
A = \\pi r^2
"""
import math
return math.pi * radius ** 2
print(calculate_area.__doc__)
The calculate_area function's docstring shows how to include more than just text. It uses a special directive to embed a properly formatted mathematical formula, which is a powerful feature for documenting technical code.
- The
.. math::directive tells compatible tools to render the formula for a circle's area,A = \pi r^2. - This directly links the Python code, which uses
math.pi * radius ** 2, to the mathematical principle it implements, improving clarity for anyone reading the documentation.
Get started with Replit
Put your knowledge into practice with Replit Agent. Describe a tool like “a web app that converts units with doctest examples” or “a financial calculator library with Google-style docstrings” and watch it get built.
Replit Agent writes the code, tests for errors, and handles deployment for you. Start building with Replit.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.


.avif)
.avif)