Code Organization in Python

Modular design
Style guidelinesDocumentation

Documentation

Comments

To clarify complicated parts of your code, you should add comments.

To add a comment prepend # to the comment's text.

Purpose

  • Explain why code exists, not what it does.
  • Clarify complex logic, edge cases, or non-obvious decisions.

💡 Assume the person reading the code knows Python, thus the code should be self-explanatory.

💡 It's easier to read well-written comments than poorly written ones. Don't skimp on punctuation and grammar!

Comments

Use sparingly inline comments and do not state the obvious!

👎 Bad

x = x + 1  # Increment x by one.

👍 Good

x = x + 1  # Compensate for boundary offset.

💡 Use 2 spaces between the code and #.

Comments

Use block comments to explain complicated operations before they commence:

🤔 What is this piece of code doing?


for row_idx, row in enumerate(csv_data, start=1):
    try:
        process_row(row)
    except InvalidDataError as e:
        log_error(f"Row {row_idx}: {e}")
Comments

Use block comments to explain complicated operations before they commence:

👎 Bad

# Loop through csv_data.
for row_idx, row in enumerate(csv_data, start=1):  # Start at 1.
    try:
        process_row(row)  # Process row.
    except InvalidDataError as e:
        log_error(f"Row {row_idx}: {e}")  # Report error.
Comments

👍 Good

# The following loop skips the first row of the CSV file because
# it contains headers that should not be treated as data.
#
# Note: Using `enumerate` with `start=1` ensures alignment with
# the original file's row numbering for error reporting.
for row_idx, row in enumerate(csv_data, start=1):
    try:
        process_row(row)
    except InvalidDataError as e:
        log_error(f"Row {row_idx}: {e}")
Docstring

A docstring is a text explanation placed at the beginning of any part of the code to describe what it does.

Purpose

  • Document modules, classes, functions, and methods.
  • Describe functionality, parameters, return values, exceptions, and usage examples.
  • Provide access to documentation at runtime via help() or __doc__.
Docstring

To add a docstring, enclose in triple double quotes (""") the documentation for module/function/class before its implementation.

def calculate_area(radius: float) -> float:
    """Calculate the area of a circle given its radius."""
    return math.pi * radius ** 2
>>> help(calculate_area)
Calculate the area of a circle given its radius.
Docstring

Conventions PEP257

  • One-line for really obvious cases.
  • Multi-line should start with a brief summary line, followed by a more elaborate description and possibly other sections.
def calculate_area(radius: float) -> float:
    """Compute the area of a circle.

    Args:
        radius (float): Radius of the circle.

    Returns:
        float: Area value.
    """
    return math.pi * radius ** 2
Docstring - Style

Google

def abc(a: int, c : Optional[list] = None):
    """_summary_

    Args:
        a (int): _description_
        c (list, optional): _description_. Defaults to None.

    Raises:
        AssertionError: _description_

    Returns:
        _type_: _description_
    """
    if a > 10:
        raise AssertionError("a is more than 10")

    return c
Docstring - Style

Sphinx

def abc(a: int, c: Optional[list] = None):
    """_summary_

    :param a: _description_
    :type a: int
    :param c: _description_, defaults to None
    :type c: list, optional
    :raises AssertionError: _description_
    :return: _description_
    :rtype: _type_
    """
    if a > 10:
        raise AssertionError("a is more than 10")

    return c
Docstring - Style

Numpy

def abc(a: int, c: Optional[list] = None):
    """_summary_

    Parameters
    ----------
    a : int
        _description_
    c : list, optional
        _description_, by default None

    Returns
    -------
    _type_
        _description_

    Raises
    ------
    AssertionError
        _description_
    """
    if a > 10:
        raise AssertionError("a is more than 10")

    return c
Docstring - Style

💡 Some linters can enforce docstring conventions. For example, Ruff supports numpy and google styles:

[tool.ruff.lint]
select = ["D"]

[tool.ruff.lint.pydocstyle]
convention = "google"

💡 Some IDEs offer plugins that can generate docstrings in various styles. Check for example autoDocstring, a VSCode extension.

Documentation

Documentation generators automatically create formatted documentation (like HTML, PDF, or Markdown) from your code's docstrings and comments.

  • Sphinx - widely used, highly customizable, convert in HTML, PDF, LaTeX, etc..
  • MkDocs - Generate HTML site from Markdown files.
  • pydoc - built-in, simple to use, generates HTML documentation.
pydoc -w my_module

This will create an my_module.html file in your current directory.

Documentation

⚠️ Update comments and docstrings when code changes to prevent misleading information!