To clarify complicated parts of your code, you should add comments.
To add a comment prepend # to the comment's text.
#
Purpose
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!
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 #.
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}")
# 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.
# 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}")
A docstring is a text explanation placed at the beginning of any part of the code to describe what it does.
help()
__doc__
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.
Conventions PEP257
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
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
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
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
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 linters can enforce docstring conventions. For example, Ruff supports numpy and google styles:
Ruff
numpy
google
[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.
autoDocstring
Documentation generators automatically create formatted documentation (like HTML, PDF, or Markdown) from your code's docstrings and comments.
pydoc -w my_module
This will create an my_module.html file in your current directory.
my_module.html
Update comments and docstrings when code changes to prevent misleading information!