Writing Function and Class Level Docstring Profiles

🏷️ Python Scripting Best Practices / Meaningful Comments and Docstrings

When you're building Python scripts that others will useβ€”or that you'll revisit months laterβ€”clear documentation is essential. Docstrings are your best tool for explaining what a function or class does, how to use it, and what to expect back. This guide walks through writing effective docstrings at both the function and class level.


🧠 Why Docstrings Matter

  • Self-documenting code – Docstrings turn your code into readable documentation without extra effort.
  • Tool-friendly – Tools like pydoc, Sphinx, and IDE help popups read docstrings automatically.
  • Team collaboration – New engineers can understand your code's purpose without reading every line.
  • Maintainability – When you revisit old code, docstrings save you from guessing your own intentions.

βš™οΈ Function-Level Docstrings

Every function should have a docstring that explains:

  • What the function does (one-line summary)
  • Parameters – names, expected types, and what they represent
  • Return value – what the function gives back, including type
  • Raises – any exceptions that might occur

Basic structure for a function docstring:

  • First line: A brief, imperative statement of what the function does.
  • Blank line (if adding more detail)
  • Args section: List each parameter with its type and description.
  • Returns section: Describe the return value and its type.
  • Raises section (optional): List exceptions and when they occur.

Example – Simple function docstring:

  • Function: calculate_disk_usage
  • Docstring content:
  • Summary: Calculate the percentage of disk space used on a given mount point.
  • Args: mount_point (str) – The filesystem path to check.
  • Returns: float – Percentage of disk space used (0.0 to 100.0).
  • Raises: FileNotFoundError – If the mount point does not exist.

Example – Function with multiple parameters:

  • Function: parse_config_file
  • Docstring content:
  • Summary: Read and parse a configuration file into a dictionary.
  • Args: file_path (str) – Absolute path to the config file.
  • encoding (str, optional) – File encoding. Defaults to 'utf-8'.
  • Returns: dict – Parsed key-value pairs from the config file.
  • Raises: ValueError – If the file format is invalid.

πŸ—οΈ Class-Level Docstrings

Class docstrings explain the purpose of the class and how it should be used. They often include:

  • Class summary – What the class represents or manages
  • Attributes – Key instance variables and their types
  • Usage example – Brief demonstration of how to instantiate and use the class

Basic structure for a class docstring:

  • First line: A concise description of the class's responsibility.
  • Blank line (if adding more detail)
  • Attributes section: List important instance attributes with types and descriptions.
  • Usage example (optional): Show a quick instantiation and method call.

Example – Simple class docstring:

  • Class: ServerMonitor
  • Docstring content:
  • Summary: Monitor CPU, memory, and disk metrics for a remote server.
  • Attributes: hostname (str) – The server's hostname or IP address.
  • timeout (int) – Connection timeout in seconds.
  • Usage: monitor = ServerMonitor('web-01', timeout=30)
  • monitor.check_health()

Example – Class with inheritance:

  • Class: DatabaseConnector
  • Docstring content:
  • Summary: Base class for connecting to various database backends.
  • Attributes: connection_string (str) – Database connection URI.
  • connection (object) – Active database connection object.
  • Note: Subclasses must implement the connect() and disconnect() methods.

πŸ“Š Function vs. Class Docstring Comparison

Aspect Function Docstring Class Docstring
Primary focus What the function does What the class represents
Key sections Args, Returns, Raises Attributes, Usage example
Tone Action-oriented (imperative) Descriptive (noun-focused)
Length Usually 3–10 lines Often 5–15 lines
Example included? Rarely Frequently

πŸ› οΈ Best Practices for Writing Docstrings

  • Keep the summary line short – Aim for 50–80 characters. It should stand alone.
  • Use consistent formatting – Stick with one style (Google, NumPy, or reStructuredText) across your project.
  • Describe why, not just what – Explain the purpose, not just the mechanics.
  • Update docstrings when code changes – Stale docstrings are worse than none.
  • Include edge cases – Mention what happens with empty inputs, None, or invalid data.
  • Use type hints alongside docstrings – Type hints in the function signature complement the docstring's type info.

πŸ•΅οΈ Common Docstring Pitfalls to Avoid

  • Writing obvious comments – Don't restate what the code clearly shows.
  • Forgetting to document exceptions – Engineers need to know what can break.
  • Using vague language – Avoid words like stuff, things, or handle.
  • Mixing docstring styles – Choose one format and use it everywhere.
  • Leaving docstrings blank – A placeholder like TODO is better than nothing.

βœ… Quick Checklist for Your Docstrings

  • [ ] Does the first line clearly state the function's or class's purpose?
  • [ ] Are all parameters documented with types and descriptions?
  • [ ] Is the return value described, including its type?
  • [ ] Are exceptions listed with conditions that trigger them?
  • [ ] For classes, are key attributes documented?
  • [ ] Is the docstring up to date with the current code?

πŸ“ Final Thoughts

Docstrings are a small investment that pays off every time someone reads your codeβ€”including your future self. By writing clear function and class-level docstrings, you make your Python scripts more accessible, maintainable, and professional. Start with the simple structures above, and refine as your projects grow.


Docstrings are multi-line comments placed inside functions and classes that describe what they do, used by Python's help system and documentation tools.

πŸ“ Example 1: Basic Function Docstring

This example shows the simplest docstring format for a single-purpose function.

def add_numbers(a, b):
    """Return the sum of two numbers."""
    return a + b

print(add_numbers(3, 5))

πŸ“€ Output: 8


πŸ“ Example 2: Multi-line Function Docstring with Parameters

This example demonstrates a docstring that describes parameters and return value using the standard format.

def calculate_area(length, width):
    """
    Calculate the area of a rectangle.

    Parameters:
    length (float): The length of the rectangle.
    width (float): The width of the rectangle.

    Returns:
    float: The area of the rectangle.
    """
    return length * width

print(calculate_area(4.5, 3.2))

πŸ“€ Output: 14.4


πŸ“ Example 3: Class Docstring with Constructor

This example shows a class-level docstring describing the class purpose and its constructor parameters.

class TemperatureSensor:
    """Represents a temperature sensor that reads and stores temperature values."""

    def __init__(self, location):
        """
        Initialize the temperature sensor with a location name.

        Parameters:
        location (str): The physical location of the sensor.
        """
        self.location = location
        self.readings = []

    def record_reading(self, value):
        """Add a temperature reading to the sensor's history."""
        self.readings.append(value)

sensor = TemperatureSensor("Engine Room")
sensor.record_reading(85.3)
print(sensor.readings)

πŸ“€ Output: [85.3]


πŸ“ Example 4: Function Docstring with Multiple Returns and Raises

This example demonstrates documenting different return conditions and possible exceptions.

def divide_numbers(dividend, divisor):
    """
    Divide two numbers and return the result.

    Parameters:
    dividend (float): The number to be divided.
    divisor (float): The number to divide by.

    Returns:
    float: The quotient of the division.

    Raises:
    ValueError: If divisor is zero.
    """
    if divisor == 0:
        raise ValueError("Cannot divide by zero")
    return dividend / divisor

try:
    result = divide_numbers(10, 0)
except ValueError as error:
    print(error)

πŸ“€ Output: Cannot divide by zero


πŸ“ Example 5: Class with Multiple Methods and Property Docstrings

This example shows a practical class with documented methods and a property that engineers might use for monitoring.

class PumpMonitor:
    """Monitors pump status and tracks operational metrics."""

    def __init__(self, pump_id):
        """
        Initialize the pump monitor with a unique identifier.

        Parameters:
        pump_id (str): The unique identifier for this pump.
        """
        self.pump_id = pump_id
        self._running = False
        self._hours_run = 0.0

    def start_pump(self):
        """Start the pump and begin tracking run time."""
        self._running = True

    def stop_pump(self):
        """Stop the pump and record the current run time."""
        self._running = False

    @property
    def total_run_hours(self):
        """
        Get the total number of hours the pump has been running.

        Returns:
        float: Total run hours accumulated.
        """
        return self._hours_run

    def add_run_time(self, hours):
        """
        Add run time to the pump's total.

        Parameters:
        hours (float): Number of hours to add.
        """
        self._hours_run += hours

pump = PumpMonitor("PUMP-101")
pump.start_pump()
pump.add_run_time(12.5)
pump.stop_pump()
print(f"Pump {pump.pump_id} ran for {pump.total_run_hours} hours")

πŸ“€ Output: Pump PUMP-101 ran for 12.5 hours


πŸ“Š Docstring Format Comparison

Feature One-Line Docstring Multi-Line Docstring
Best for Simple functions with clear purpose Complex functions or classes
Structure Single line in triple quotes Summary line, blank line, then details
Parameter docs Not included Included with types and descriptions
Return docs Not included Included with type and description
Raises docs Not included Included when exceptions are raised
Example use def add(a, b): """Return sum.""" def calc(x): """... Parameters: ... Returns: ..."""

When you're building Python scripts that others will useβ€”or that you'll revisit months laterβ€”clear documentation is essential. Docstrings are your best tool for explaining what a function or class does, how to use it, and what to expect back. This guide walks through writing effective docstrings at both the function and class level.


🧠 Why Docstrings Matter

  • Self-documenting code – Docstrings turn your code into readable documentation without extra effort.
  • Tool-friendly – Tools like pydoc, Sphinx, and IDE help popups read docstrings automatically.
  • Team collaboration – New engineers can understand your code's purpose without reading every line.
  • Maintainability – When you revisit old code, docstrings save you from guessing your own intentions.

βš™οΈ Function-Level Docstrings

Every function should have a docstring that explains:

  • What the function does (one-line summary)
  • Parameters – names, expected types, and what they represent
  • Return value – what the function gives back, including type
  • Raises – any exceptions that might occur

Basic structure for a function docstring:

  • First line: A brief, imperative statement of what the function does.
  • Blank line (if adding more detail)
  • Args section: List each parameter with its type and description.
  • Returns section: Describe the return value and its type.
  • Raises section (optional): List exceptions and when they occur.

Example – Simple function docstring:

  • Function: calculate_disk_usage
  • Docstring content:
  • Summary: Calculate the percentage of disk space used on a given mount point.
  • Args: mount_point (str) – The filesystem path to check.
  • Returns: float – Percentage of disk space used (0.0 to 100.0).
  • Raises: FileNotFoundError – If the mount point does not exist.

Example – Function with multiple parameters:

  • Function: parse_config_file
  • Docstring content:
  • Summary: Read and parse a configuration file into a dictionary.
  • Args: file_path (str) – Absolute path to the config file.
  • encoding (str, optional) – File encoding. Defaults to 'utf-8'.
  • Returns: dict – Parsed key-value pairs from the config file.
  • Raises: ValueError – If the file format is invalid.

πŸ—οΈ Class-Level Docstrings

Class docstrings explain the purpose of the class and how it should be used. They often include:

  • Class summary – What the class represents or manages
  • Attributes – Key instance variables and their types
  • Usage example – Brief demonstration of how to instantiate and use the class

Basic structure for a class docstring:

  • First line: A concise description of the class's responsibility.
  • Blank line (if adding more detail)
  • Attributes section: List important instance attributes with types and descriptions.
  • Usage example (optional): Show a quick instantiation and method call.

Example – Simple class docstring:

  • Class: ServerMonitor
  • Docstring content:
  • Summary: Monitor CPU, memory, and disk metrics for a remote server.
  • Attributes: hostname (str) – The server's hostname or IP address.
  • timeout (int) – Connection timeout in seconds.
  • Usage: monitor = ServerMonitor('web-01', timeout=30)
  • monitor.check_health()

Example – Class with inheritance:

  • Class: DatabaseConnector
  • Docstring content:
  • Summary: Base class for connecting to various database backends.
  • Attributes: connection_string (str) – Database connection URI.
  • connection (object) – Active database connection object.
  • Note: Subclasses must implement the connect() and disconnect() methods.

πŸ“Š Function vs. Class Docstring Comparison

Aspect Function Docstring Class Docstring
Primary focus What the function does What the class represents
Key sections Args, Returns, Raises Attributes, Usage example
Tone Action-oriented (imperative) Descriptive (noun-focused)
Length Usually 3–10 lines Often 5–15 lines
Example included? Rarely Frequently

πŸ› οΈ Best Practices for Writing Docstrings

  • Keep the summary line short – Aim for 50–80 characters. It should stand alone.
  • Use consistent formatting – Stick with one style (Google, NumPy, or reStructuredText) across your project.
  • Describe why, not just what – Explain the purpose, not just the mechanics.
  • Update docstrings when code changes – Stale docstrings are worse than none.
  • Include edge cases – Mention what happens with empty inputs, None, or invalid data.
  • Use type hints alongside docstrings – Type hints in the function signature complement the docstring's type info.

πŸ•΅οΈ Common Docstring Pitfalls to Avoid

  • Writing obvious comments – Don't restate what the code clearly shows.
  • Forgetting to document exceptions – Engineers need to know what can break.
  • Using vague language – Avoid words like stuff, things, or handle.
  • Mixing docstring styles – Choose one format and use it everywhere.
  • Leaving docstrings blank – A placeholder like TODO is better than nothing.

βœ… Quick Checklist for Your Docstrings

  • [ ] Does the first line clearly state the function's or class's purpose?
  • [ ] Are all parameters documented with types and descriptions?
  • [ ] Is the return value described, including its type?
  • [ ] Are exceptions listed with conditions that trigger them?
  • [ ] For classes, are key attributes documented?
  • [ ] Is the docstring up to date with the current code?

πŸ“ Final Thoughts

Docstrings are a small investment that pays off every time someone reads your codeβ€”including your future self. By writing clear function and class-level docstrings, you make your Python scripts more accessible, maintainable, and professional. Start with the simple structures above, and refine as your projects grow.

Interactive Views

You are currently in πŸ“š All-in-One mode. Use the tabs at the top to switch to πŸ“– Theory Only or πŸ’» Code Only views.

Docstrings are multi-line comments placed inside functions and classes that describe what they do, used by Python's help system and documentation tools.

πŸ“ Example 1: Basic Function Docstring

This example shows the simplest docstring format for a single-purpose function.

def add_numbers(a, b):
    """Return the sum of two numbers."""
    return a + b

print(add_numbers(3, 5))

πŸ“€ Output: 8


πŸ“ Example 2: Multi-line Function Docstring with Parameters

This example demonstrates a docstring that describes parameters and return value using the standard format.

def calculate_area(length, width):
    """
    Calculate the area of a rectangle.

    Parameters:
    length (float): The length of the rectangle.
    width (float): The width of the rectangle.

    Returns:
    float: The area of the rectangle.
    """
    return length * width

print(calculate_area(4.5, 3.2))

πŸ“€ Output: 14.4


πŸ“ Example 3: Class Docstring with Constructor

This example shows a class-level docstring describing the class purpose and its constructor parameters.

class TemperatureSensor:
    """Represents a temperature sensor that reads and stores temperature values."""

    def __init__(self, location):
        """
        Initialize the temperature sensor with a location name.

        Parameters:
        location (str): The physical location of the sensor.
        """
        self.location = location
        self.readings = []

    def record_reading(self, value):
        """Add a temperature reading to the sensor's history."""
        self.readings.append(value)

sensor = TemperatureSensor("Engine Room")
sensor.record_reading(85.3)
print(sensor.readings)

πŸ“€ Output: [85.3]


πŸ“ Example 4: Function Docstring with Multiple Returns and Raises

This example demonstrates documenting different return conditions and possible exceptions.

def divide_numbers(dividend, divisor):
    """
    Divide two numbers and return the result.

    Parameters:
    dividend (float): The number to be divided.
    divisor (float): The number to divide by.

    Returns:
    float: The quotient of the division.

    Raises:
    ValueError: If divisor is zero.
    """
    if divisor == 0:
        raise ValueError("Cannot divide by zero")
    return dividend / divisor

try:
    result = divide_numbers(10, 0)
except ValueError as error:
    print(error)

πŸ“€ Output: Cannot divide by zero


πŸ“ Example 5: Class with Multiple Methods and Property Docstrings

This example shows a practical class with documented methods and a property that engineers might use for monitoring.

class PumpMonitor:
    """Monitors pump status and tracks operational metrics."""

    def __init__(self, pump_id):
        """
        Initialize the pump monitor with a unique identifier.

        Parameters:
        pump_id (str): The unique identifier for this pump.
        """
        self.pump_id = pump_id
        self._running = False
        self._hours_run = 0.0

    def start_pump(self):
        """Start the pump and begin tracking run time."""
        self._running = True

    def stop_pump(self):
        """Stop the pump and record the current run time."""
        self._running = False

    @property
    def total_run_hours(self):
        """
        Get the total number of hours the pump has been running.

        Returns:
        float: Total run hours accumulated.
        """
        return self._hours_run

    def add_run_time(self, hours):
        """
        Add run time to the pump's total.

        Parameters:
        hours (float): Number of hours to add.
        """
        self._hours_run += hours

pump = PumpMonitor("PUMP-101")
pump.start_pump()
pump.add_run_time(12.5)
pump.stop_pump()
print(f"Pump {pump.pump_id} ran for {pump.total_run_hours} hours")

πŸ“€ Output: Pump PUMP-101 ran for 12.5 hours


πŸ“Š Docstring Format Comparison

Feature One-Line Docstring Multi-Line Docstring
Best for Simple functions with clear purpose Complex functions or classes
Structure Single line in triple quotes Summary line, blank line, then details
Parameter docs Not included Included with types and descriptions
Return docs Not included Included with type and description
Raises docs Not included Included when exceptions are raised
Example use def add(a, b): """Return sum.""" def calc(x): """... Parameters: ... Returns: ..."""