TL;DR: 8 Key Python Docstring Examples
- Google Style: Highly readable and structured; great for auto-generating API docs. Best for large, collaborative projects.
- NumPy/SciPy Style: Verbose and detailed; the standard for scientific and data-heavy libraries.
- PEP 257/Sphinx: The foundational style using reStructuredText. Perfect for open-source projects needing comprehensive documentation websites.
- Doctest Format: Embeds runnable tests directly in docstrings, guaranteeing examples are always correct.
- RESTful API / OpenAPI: Describes HTTP endpoints and schemas; essential for web APIs and auto-generating interactive docs.
- Minimal/Pragmatic: A simple one-liner for self-explanatory functions. Relies heavily on clear code and type hints.
- Dataclass/Type-Hinted: Modern approach where type hints in the code handle type documentation, leaving the docstring to explain the why.
- Epydoc/Javadoc Style: A legacy, tag-based format found in older codebases. Good to recognize but less common for new projects.
Table of Contents
- 1. Google Style Docstrings
- 2. NumPy/SciPy Style Docstrings
- 3. PEP 257 / Sphinx-Compatible Docstrings
- 4. Doctest Format Docstrings
- 5. RESTful API / OpenAPI Docstrings
- 6. Epydoc / Javadoc-Style Docstrings
- 7. Minimal/Pragmatic Docstrings
- 8. Dataclass / Type-Hinted Docstrings
- Comparison of 8 Python Docstring Styles
- Final Thoughts
Writing good documentation is non-negotiable for maintainable, scalable, and collaborative software projects. In Python, the docstring is the cornerstone of this practice. It’s not just a comment; it’s a feature of the language itself, accessible at runtime and essential for generating automated documentation.
However, “writing a docstring” isn’t a one-size-fits-all instruction. The Python ecosystem supports several competing styles, each with its own strengths. In my experience, choosing the right format or even understanding one you’ve inherited can be a significant hurdle. This is where a practical collection of python docstring examples becomes invaluable.
This guide provides clear, actionable examples for the most common docstring formats you’ll encounter. We’ll break down Google Style, NumPy/SciPy, Sphinx, and others, offering a practical analysis of when and why to use each one. You’ll learn not just what these docstrings look like, but how they function in real-world scenarios.
1. Google Style Docstrings
The Google Style docstring is a highly structured and readable format defined in the Google Python Style Guide. It’s renowned for its clarity, making it one of the most popular python docstring examples for projects that prioritize maintainability. This style enforces specific sections like Args, Returns, and Raises, which tools like Sphinx (with the Napoleon extension) can parse to auto-generate beautiful API documentation.
Example Breakdown
Let’s look at a function to fetch user data, documented using the Google style.
def fetch_user_data(user_id: int, include_profile: bool = True) -> dict:
"""Fetches user data from the database.
This function queries the user database for a specific user ID
and can optionally include extended profile information.
Args:
user_id (int): The unique identifier for the user.
include_profile (bool): If True, includes the user's profile
data in the response. Defaults to True.
Returns:
dict: A dictionary containing user data. Returns an empty
dictionary if the user is not found.
Raises:
ValueError: If the user_id is not a positive integer.
"""
if not isinstance(user_id, int) or user_id <= 0:
raise ValueError("User ID must be a positive integer.")
# ... database fetching logic here ...
user_data = {"id": user_id, "name": "Jane Doe"}
if include_profile:
user_data["profile"] = {"email": "[email protected]"}
return user_data
Strategic Analysis & Actionable Takeaways
Clarity Through Structure: The
Args,Returns, andRaisessections create a predictable and scannable format. Developers immediately know where to look.Type Hinting Integration: The style seamlessly combines docstring type declarations (
user_id (int):) with modern Python type hints (user_id: int).Descriptive Parameter Details: Each argument includes its name, type, and a concise description. For optional parameters, clearly state the default behavior (
Defaults to True).
Key Takeaway: Adopt the Google style when your priority is generating clean, automated API documentation and enforcing a strict, consistent format across a large team. Its structure minimizes ambiguity and is ideal for complex functions and APIs.
2. NumPy/SciPy Style Docstrings
The NumPy/SciPy style docstring is a comprehensive format born from the needs of the scientific computing community. It’s meticulously detailed, making it the standard for projects like NumPy, SciPy, and Pandas. This format is designed to clearly document complex functions with numerous parameters. Like Google style, it’s supported by Sphinx, making it an excellent choice among python docstring examples for technical documentation.

Caption: The NumPy docstring format uses clear, underlined sections to organize complex information about parameters, return values, and related functions.
Example Breakdown
Letβs examine a function that calculates the dot product of two vectors, documented in the NumPy style.
import numpy as np
def vector_dot_product(x: np.ndarray, y: np.ndarray) -> float:
"""Calculate the dot product of two vectors.
This function takes two 1-D arrays of the same size and computes
their dot product.
Parameters
----------
x : np.ndarray
First input vector. A 1-dimensional array of numbers.
y : np.ndarray
Second input vector. Must have the same shape as `x`.
Returns
-------
float
The scalar dot product of the input vectors.
Raises
------
ValueError
If the input arrays are not 1-dimensional or have mismatched shapes.
See Also
--------
numpy.dot : Equivalent function in the NumPy library.
"""
if x.ndim != 1 or y.ndim != 1:
raise ValueError("Input arrays must be 1-dimensional.")
if x.shape != y.shape:
raise ValueError("Input arrays must have the same shape.")
return np.dot(x, y)
Strategic Analysis & Actionable Takeaways
Explicit Section Headers: The NumPy style uses underlined headers (
Parameters,Returns,Raises). This visual separation makes dense docstrings highly readable.Detailed Parameter Descriptions: Each parameter is defined with its name, type, and description on separate lines, allowing for more extensive explanations.
Contextual Cross-Referencing: The
See Alsosection is a powerful feature for building an interconnected documentation system, guiding users to related functions.
Key Takeaway: Use the NumPy/SciPy style for technical libraries where functions have complex parameters, especially arrays. Its structured, verbose format is perfect for documenting mathematical details and data shapes.
3. PEP 257 / Sphinx-Compatible Docstrings
PEP 257 is the foundational document defining the conventions for good docstrings in Python. It’s the community’s official standard, emphasizing simplicity and consistency. Docstrings following this convention are designed to be parsed by automated tools, most notably Sphinx, to generate professional documentation. This style serves as the base for many other formats, making it one of the most fundamental python docstring examples to master.
Example Breakdown
Let’s examine a class documentation that adheres to PEP 257 principles and is formatted with reStructuredText (reST) for Sphinx.
class APIClient:
"""A client to interact with a remote API.
This class provides a high-level interface for making HTTP requests
to a specified API endpoint. It handles authentication and
session management automatically.
:param base_url: The base URL for the API endpoint.
:type base_url: str
:param api_key: The API key for authentication.
:type api_key: str
"""
def __init__(self, base_url: str, api_key: str):
self.base_url = base_url
self._api_key = api_key
# ... session initialization logic ...
def get_resource(self, resource_id: int) -> dict:
"""Retrieve a specific resource by its ID.
:param resource_id: The ID of the resource to fetch.
:type resource_id: int
:return: A dictionary representing the resource.
:rtype: dict
:raises ConnectionError: If the API is unreachable.
"""
# ... request logic here ...
if resource_id <= 0:
raise ValueError("Resource ID must be positive.")
return {"id": resource_id, "data": "sample data"}
Strategic Analysis & Actionable Takeaways
Foundation of All Styles: PEP 257 establishes the core principles: a one-line summary followed by a more descriptive paragraph. Understanding this is crucial.
reStructuredText (reST) Integration: This style relies on reST directives like
:param:,:type:,:return:, and:raises:. While verbose, this format is powerful, directly feeding into the Sphinx documentation engine.Explicit Type Declaration: This style often separates parameter name and type into
:param:and:type:tags. This explicitness ensures maximum compatibility with documentation tools.
Key Takeaway: Adopt the PEP 257/Sphinx style when building libraries or open-source projects where generating comprehensive, cross-referenced documentation is a primary goal. To dive deeper, you can learn more about function documentation in Python and its core principles.
4. Doctest Format Docstrings
The Doctest format is a unique approach that embeds executable test cases directly within your docstrings. As one of the most practical python docstring examples, it serves a dual purpose: it documents the code’s behavior with concrete examples and simultaneously acts as a verifiable test suite. Python’s built-in doctest module can discover and run these examples, ensuring your documentation never becomes outdated.

Example Breakdown
Letβs examine a simple function for calculating an average, documented with integrated doctests.
import doctest
def calculate_average(numbers: list[float]) -> float:
"""Calculates the average of a list of numbers.
This function returns the arithmetic mean of a list containing
numeric values. It handles empty lists by returning 0.0.
Examples:
>>> calculate_average([1, 2, 3, 4, 5])
3.0
>>> calculate_average([10.5, 19.5])
15.0
>>> calculate_average([])
0.0
>>> calculate_average([-1, 1])
0.0
"""
if not numbers:
return 0.0
return sum(numbers) / len(numbers)
if __name__ == "__main__":
doctest.testmod() # Runs the tests embedded in the docstring
Strategic Analysis & Actionable Takeaways
Living Documentation: The primary advantage is that your examples are guaranteed to be correct. If the code changes and breaks an example, the doctest will fail.
Clarity Through Demonstration: Doctests show users exactly how to use the function with real inputs and expected outputs. This is often more intuitive than text alone.
Simplified Testing: For simple functions, doctests provide a low-friction way to add test coverage without the overhead of a separate test file.
Key Takeaway: Use the Doctest format when you want to provide clear, executable examples that double as a basic test suite. It is ideal for utility libraries and functions whose behavior is best explained by demonstration.
5. RESTful API / OpenAPI Docstrings
When documenting web services, standard docstrings fall short. RESTful API docstrings, structured according to the OpenAPI Specification (formerly Swagger), are designed for this purpose. They describe HTTP endpoints, request/response models, and status codes. This format is a prime example of how python docstring examples can power entire developer ecosystems.

Example Breakdown
Modern Python web frameworks like FastAPI integrate OpenAPI directly into the docstring. This allows developers to write documentation right alongside their endpoint logic.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items/", status_code=201)
def create_item(item: Item):
"""
Creates a new item.
This endpoint adds a new item to the inventory based on the
provided data. It performs validation and returns the created
item's data.
- **name**: The name of the item.
- **price**: The selling price of the item.
"""
# ... logic to save the item to a database ...
return {"message": "Item created successfully", "item_data": item}
Strategic Analysis & Actionable Takeaways
Machine-Readable by Design: The primary goal is machine-readability. Tools like Swagger UI and ReDoc consume the generated OpenAPI schema to create interactive documentation.
Framework Integration: Frameworks like FastAPI use these docstrings to automatically build the API schema. The docstring’s summary becomes the endpoint’s description.
Single Source of Truth: This approach makes the code the single source of truth for the API’s contract. When the code changes, a simple docstring update ensures the public documentation is also updated. You can explore a variety of these implementations with these OpenAPI examples.
Key Takeaway: Use the OpenAPI docstring pattern when building any web API. It transforms documentation from a static, manual task into a dynamic, automated process.
6. Epydoc / Javadoc-Style Docstrings
The Epydoc style is a format inspired by Java’s Javadoc comment system. It uses @ tags like @param and @return to explicitly label different parts of the docstring. While less common in new Python projects, which often prefer Google or NumPy styles, its influence is still seen in some legacy codebases.
Example Breakdown
Let’s adapt our function to use the Epydoc style.
def fetch_user_data(user_id, include_profile=True):
"""Fetches user data from the database.
This function queries the user database for a specific user ID
and can optionally include extended profile information.
@param user_id: The unique identifier for the user.
@type user_id: int
@param include_profile: If True, includes the user's profile
data in the response.
@type include_profile: bool
@return: A dictionary containing user data. Returns an empty
dictionary if the user is not found.
@rtype: dict
@raise ValueError: If the user_id is not a positive integer.
"""
if not isinstance(user_id, int) or user_id <= 0:
raise ValueError("User ID must be a positive integer.")
# ... database fetching logic here ...
user_data = {"id": user_id, "name": "Jane Doe"}
if include_profile:
user_data["profile"] = {"email": "[email protected]"}
return user_data
Strategic Analysis & Actionable Takeaways
Explicit Tagging: The use of
@tags like@param,@type, and@returnleaves no ambiguity. Each piece of metadata is clearly marked.Separation of Concerns: This style strictly separates the parameter’s name (
@param) from its type (@type), making it verbose but granular.Legacy System Compatibility: Its primary relevance today is in maintaining older codebases. Understanding this style is crucial for working on long-running enterprise projects.
Key Takeaway: Use the Epydoc style only when you must maintain consistency within a legacy project. For new projects, choose a more modern format like Google or NumPy style.
7. Minimal/Pragmatic Docstrings
Not all functions require an exhaustive docstring. The minimal, or pragmatic, approach champions brevity, advocating for documentation only where it adds real value. This style is perfect for simple, self-explanatory functions where clear naming and type hints convey most of the necessary information.
Example Breakdown
Consider a simple helper function to format a user’s full name. Its purpose is clear from its name and type hints, making a lengthy docstring redundant.
def format_full_name(first_name: str, last_name: str) -> str:
"""Joins the first and last name into a single string."""
if not first_name or not last_name:
return ""
return f"{first_name.strip().title()} {last_name.strip().title()}"
Strategic Analysis & Actionable Takeaways
Clarity Over Verbosity: The one-line summary is sufficient. It confirms the function’s purpose without restating the obvious.
Reliance on Code Readability: A minimal docstring is only effective when the function name (
format_full_name) and type hints (str) are exceptionally clear.Reduced Maintenance: For simple utilities, overly detailed docstrings become a liability. This lean approach ensures documentation is less likely to become stale. You can learn more about keeping documentation in sync with your code in this guide on function documentation.
Key Takeaway: Employ minimal docstrings for internal helper functions or simple, self-evident code. This pragmatic approach depends on writing highly readable code with descriptive names and strong type hinting.
8. Dataclass / Type-Hinted Docstrings
Modern Python (3.6+) encourages using type hints directly in the function signature, as defined in PEP 484. This shifts the responsibility of documenting types from the docstring to the code itself, leading to cleaner documentation. This is one of the most practical python docstring examples for projects leveraging frameworks like FastAPI or Pydantic. The docstring can then focus on explaining the why and how.
Example Breakdown
Let’s look at a function that processes a user profile defined using a Pydantic BaseModel. The docstring is minimal because the type hints are self-documenting.
from typing import Optional
from pydantic import BaseModel, Field
class UserProfile(BaseModel):
"""Represents a user's profile data model."""
user_id: int = Field(..., description="The unique user identifier.")
username: str = Field(..., description="The user's public username.")
bio: Optional[str] = None
def update_user_bio(profile: UserProfile, new_bio: str) -> UserProfile:
"""Updates the biography for a given user profile.
This function takes a user profile object and sets a new bio,
returning the modified profile. It relies on the UserProfile model
for data validation.
Args:
profile (UserProfile): The user profile object to update.
new_bio (str): The new biography text for the user.
Returns:
UserProfile: The updated user profile object with the new bio.
"""
profile.bio = new_bio
return profile
Strategic Analysis & Actionable Takeaways
Single Source of Truth: Type information (
UserProfile,str) resides in the function signature, eliminating drift between code and docs.Reduced Docstring Boilerplate: Since types are explicit in the code, the docstring can be lighter. The
Argssection explains the purpose of each parameter, not its type.IDE and Linter Integration: This style is highly compatible with modern IDEs, linters, and static analysis tools like Mypy, which improves developer productivity.
Key Takeaway: Adopt this type-hint-first approach in a modern Python environment, especially with libraries that use type hints for validation or serialization. It creates more maintainable and less redundant documentation.
Comparison of 8 Python Docstring Styles
| Style | π Implementation Complexity | β‘ Resource / Tooling | β Expected Outcomes | π Ideal Use Cases | π‘ Key Advantages / Tips |
|---|---|---|---|---|---|
| Google Style Docstrings | π Medium β structured sections, needs consistency | β‘ Sphinx/Doc generators; moderate maintenance | ββββ β Clear, scannable API docs | Large projects, team APIs, public libraries | π‘ Include Args/Returns, use concrete types and examples |
| NumPy/SciPy Style Docstrings | π High β verbose, detailed shape/type specs | β‘ Sphinx (numpydoc), extensive examples; higher authoring cost | βββββ β Precise for numerical APIs and arrays | Scientific computing, numerical libraries, research code | π‘ Document array shapes/dtypes and provide multiple examples |
| PEP 257 / Sphinx-Compatible | π Low β minimal, consistent convention | β‘ Sphinx, doctest support; low overhead | βββ β Clean, general-purpose and standards-compliant | Standard Python libs, general open-source projects | π‘ Start with one-line summary; use reST and runnable doctests |
| Doctest Format Docstrings | π Medium β embed executable examples, maintain outputs | β‘ Python doctest, pytest –doctest-modules; CI recommended | βββ β Docs double as tests; catches drift early | Tutorials, simple functions, test-driven docs | π‘ Keep examples simple, use ellipsis for long output, run in CI |
| RESTful API / OpenAPI Docstrings | π High β spec-driven, endpoint and schema detail | β‘ OpenAPI/Swagger, FastAPI/ReDoc; schema validation tools | ββββ β Interactive docs and clear API contracts | Web APIs, microservices, public endpoints | π‘ Document status codes and example bodies; use decorators |
| Epydoc / Javadoc-Style Docstrings | π Medium β tag-based, can be verbose/outdated | β‘ Epydoc (legacy); limited modern tool support | ββ β Strong metadata but less Pythonic and declining support | Legacy codebases, Java-to-Python migrations | π‘ Prefer migrating to Google/NumPy styles; add type hints |
| Minimal / Pragmatic Docstrings | π Low β very brief, low maintenance | β‘ Rely on clear names and PEP 484 type hints; minimal tooling | βββ β Fast to write, low drift for simple code | Internal helpers, prototypes, simple utilities | π‘ Document “why” not “what”; combine with type hints |
| Dataclass / Type-Hinted Docstrings | π LowβMedium β leverage code-level types, less doc text | β‘ mypy, Pydantic, IDEs (PyCharm/VS Code); static type checkers | ββββ β Strong IDE/autocomplete and type safety | Modern Python projects, APIs with validation, data pipelines | π‘ Use Optional/Union/TypedDict for clarity; keep docstrings concise |
Final Thoughts
We’ve explored a wide spectrum of python docstring examples, from the structured verbosity of Google and NumPy styles to the lean, pragmatic approach of minimal docstrings. Each style serves a unique purpose. The key isn’t to find a single “best” style, but to understand the trade-offs and choose the one that aligns with your project’s goals.
A great docstring is more than just a comment; it’s a contract. It tells other developers what a piece of code promises to do, what it expects as input, and what it will deliver as output. This clarity is the foundation of maintainable software development.
Your Actionable Takeaways
As you move forward, keep these core principles in mind:
- Consistency is King: Choose a style and stick with it. Inconsistent documentation is often more confusing than no documentation at all.
- The “Why” Matters Most: Don’t just explain what the code does; explain why it exists. What problem does this function solve?
- Docstrings are for Humans and Machines: They must be readable for developers and parsable for tools that generate documentation sites.
- Evolve Your Documentation: Documentation is not a one-time task. An outdated docstring is a trap. Make documentation updates a required part of your pull request process.
Mastering the art of writing effective docstrings is a significant step toward becoming a more proficient developer. Itβs a practice that pays dividends in reduced onboarding time, fewer bugs, and a more resilient codebase.
Keeping docstrings accurate and in sync with your code is a continuous challenge, especially in fast-moving projects. If you find your team struggling with documentation drift, consider automating the process. DeepDocs is a GitHub-native AI app that keeps your documentation up to date by automatically detecting code changes and updating the relevant docs, ensuring they never fall out of sync again.

Leave a Reply