Python Comments & Docstrings: Writing Clear Code and Documentation

Python comments explain code to humans, while docstrings document modules, classes, functions, and methods in a way Python can read at runtime. Use # for notes that should be ignored by the interpreter, and use triple-quoted docstrings when you want built-in documentation that tools like help() can show. The sections below show the syntax, how docstrings behave, common mistakes, and how to choose between them.

Difficulty: Beginner

Helpful to know first: basic Python syntax, functions, and string literals.

How Python Comments and Docstrings Work

Comments and docstrings both help people read code, but they do different jobs. A comment starts with # and Python ignores it completely. A docstring is a string literal placed as the first statement in a module, class, function, or method. Python stores that string in the object’s __doc__ attribute and tools can display it later.

Here is the smallest useful example of each:

Terminal
# This is a comment.
def greet(name):
    """Return a greeting for name."""
    return f"Hello, {name}!"

print(greet("Ada"))
# Output: Hello, Ada!

The comment above the function is ignored when the program runs. The docstring inside the function is not ignored in the same way: Python keeps it attached to the function object, so documentation tools can read it.

A docstring is still a string literal. It is only treated as documentation when it appears in the first statement position inside a module, class, function, or method.

When to Use Comments and When to Use Docstrings

Use comments for short explanations about code that are not obvious from the code itself. Use docstrings for API-style documentation: what a function does, what arguments it expects, what it returns, and any important side effects or errors.

Comments explain the why

Comments are best when you need to explain a decision, a workaround, or a warning about unusual code. They are often the right place for context that does not belong in the program output.

Python
tax_rate = 0.07
# Rounded up because the payment processor accepts cents only.
total_cents = round(price * (1 + tax_rate) * 100)

That comment does not repeat the code. It explains a business rule the code alone does not show.

Docstrings explain the what

Docstrings are useful when another person calls your function or imports your module. They should describe behavior in a concise, structured way.

Python
def celsius_to_fahrenheit(celsius):
    """Convert a temperature from Celsius to Fahrenheit.

    Args:
        celsius: Temperature in degrees Celsius.

    Returns:
        Temperature in degrees Fahrenheit.
    """
    return (celsius * 9 / 5) + 32

print(celsius_to_fahrenheit(25))
# Output: 77.0

This docstring describes the function’s purpose and input in plain language. The code itself handles the calculation.

How Triple-Quoted Docstrings Behave in Python

Most docstrings use triple double quotes, such as """text""". Python also allows triple single quotes, but triple double quotes are the common style in PEP 8 code. The content can span multiple lines, which makes it suitable for short summaries plus details.

A module docstring goes at the top of a file. A function docstring goes as the first statement inside the function body. A class docstring goes directly under the class line.

Python
"""Utilities for formatting temperatures."""

class Thermometer:
    """Represent a thermometer reading in Celsius."""

    def __init__(self, celsius):
        self.celsius = celsius

print(Thermometer.__doc__)
# Output: Represent a thermometer reading in Celsius.

Python stores the first string in each of those positions as the object’s docstring. If the first statement is not a string literal, there is no docstring for that object.

Docstrings become available at runtime

You can read docstrings through the __doc__ attribute or with help(). That is one reason docstrings are different from comments: comments vanish before Python creates the object.

Python
def square(number):
    """Return the square of number."""
    return number * number

print(square.__doc__)
# Output: Return the square of number.

That output comes from Python storing the docstring on the function object. A comment could never be read this way because comments are removed before execution.

Worked Examples of Comments and Docstrings in Real Code

Explaining a non-obvious calculation with a comment

Use a comment when the reason for the calculation is more important than the formula itself. The code below includes a business rule that would be hard to infer from the math alone.

Python
subtotal = 49.99
shipping = 5.00
discount = 10.00

# Apply the discount before shipping because shipping is fixed.
total = subtotal - discount + shipping

print(total)
# Output: 44.99

The comment tells you why the formula is arranged that way. If the rule changes later, the code reviewer knows where to look.

Documenting a helper function with a docstring

Use a docstring when a function is meant to be reused. A caller should be able to understand the contract without reading the function body.

Python
def clamp(value, minimum, maximum):
    """Return value constrained to the inclusive range [minimum, maximum]."""
    if value < minimum:
        return minimum
    if value > maximum:
        return maximum
    return value

print(clamp(12, 0, 10))
# Output: 10

This docstring is short and direct. It tells the reader the behavior without restating every line of code.

Using a module docstring for a file-level summary

A module docstring belongs at the top of a Python file and describes the file as a whole. It is common in scripts and reusable modules.

Python
"""Command-line tools for generating study reminders."""

def build_message(name):
    return f"Study hard, {name}!"

print(build_message("Mina"))
# Output: Study hard, Mina!

If another developer opens the file, the top-level docstring gives them the purpose before they read the implementation details.

Combining comments and docstrings in one module

You often need both. The docstring describes the public interface, while comments explain an unusual implementation detail inside the function.

Python
"""Parse and normalize user names."""

def normalize_name(name):
    """Return name with extra spaces removed and words capitalized."""
    # split() without arguments removes repeated whitespace safely.
    return " ".join(part.capitalize() for part in name.split())

print(normalize_name("  aDa   loVeLaCe  "))
# Output: Ada Lovelace

The docstring explains the function’s contract. The inline comment explains one detail of the implementation that is easy to miss.

How Comments and Docstrings Behave in Detail

Python ignores comments completely

A comment starts with # and runs to the end of the line. Python does not execute it, store it, or expose it at runtime. That means comments cannot affect program output unless you accidentally comment out code you meant to run.

Python
x = 3
# x = 5
print(x)
# Output: 3

The commented assignment never runs, so x stays 3.

Only the first string literal becomes a docstring

Python treats the first statement in a module, class, function, or method specially if that statement is a string literal. Later string literals are just ordinary expressions and are ignored if they do nothing.

Python
def example():
    """This is the docstring."""
    "This is just a string expression."""
    return 1

print(example.__doc__)
# Output: This is the docstring.

Only the first string is stored as the function’s documentation. The second string is not part of the docstring.

If you want to suppress the value of a stray string expression, do not rely on it. Place your docstring first and then write real code.

Docstrings are not meant to replace comments everywhere

A docstring documents the public meaning of an object. It is not the best place for temporary notes, debugging notes, or implementation details that only matter locally inside one block of code. For those, use comments.

Python
def load_scores(path):
    """Return a list of integer scores from a text file."""
    # Ignore blank lines because students may add extra spacing.
    with open(path, "r", encoding="utf-8") as file:
        return [int(line) for line in file if line.strip()]

The docstring tells you what the function returns. The comment explains why a line is skipped.

Comments and docstrings both need to stay accurate

Old documentation is often worse than no documentation. If code changes, the comment or docstring may need to change too. A misleading docstring can confuse readers and automated tools just like a misleading comment can confuse humans.

Python
def area(radius):
    """Return the circumference of a circle."""
    return 3.14159 * radius * radius

print(area(2))
# Output: 12.56636

The code calculates area, but the docstring says circumference. That mismatch is a bug in documentation, even though the program still runs.

Predict the Output

Check your understanding of how Python treats comments and docstrings. Try to answer before opening each solution.

What does this print?

Python
def describe():
    """First line."""
    """Second line."""
    return describe.__doc__

print(describe())
Show answer

It prints First line.

The first string literal inside the function becomes the docstring. The second string literal is just another string expression, so it does not replace the docstring.

What happens here?

Python
value = 10
# value = 99
print(value)
Show answer

It prints 10.

The commented line is ignored completely, so the assignment to 99 never happens.

Find the Bug

Find the mistake in this function’s documentation. The code runs, but the documentation does not match the behavior.

Python
def double_and_add_one(number):
    """Return number doubled and increased by one."""
    return number * 2 - 1

print(double_and_add_one(4))
# Output: 7
Show answer

The bug is the docstring. It says the function adds one, but the code subtracts one.

Fixed code:

Python
def double_and_add_one(number):
    """Return number doubled and increased by one."""
    return number * 2 + 1

print(double_and_add_one(4))
# Output: 9

The corrected version matches the docstring and the name of the function.

Common Mistakes with Comments and Docstrings

Using a comment where a docstring is expected

New Python programmers often put a comment under a function and assume it becomes documentation. It does not. Tools like help() and many editors only use docstrings.

Problem: The comment is visible to humans in the file, but Python does not store it as the function’s documentation.

Python
def greet(name):
    # Return a greeting for name.
    return f"Hello, {name}!"

print(greet.__doc__)
# Output: None

Fix: Put a triple-quoted docstring as the first statement in the function.

Python
def greet(name):
    """Return a greeting for name."""
    return f"Hello, {name}!"

print(greet.__doc__)
# Output: Return a greeting for name.

The corrected version works because Python stores the first string literal as the docstring.

Placing code before the docstring

A docstring must be the first statement in the object body. If you write code first, the string is no longer treated as documentation.

Problem: The string is not first, so Python treats it as an unused expression instead of a docstring.

Python
def add(a, b):
    result = a + b
    """Return the sum of a and b."""
    return result

print(add.__doc__)
# Output: None

Fix: Move the docstring to the top of the function body.

Python
def add(a, b):
    """Return the sum of a and b."""
    result = a + b
    return result

print(add.__doc__)
# Output: Return the sum of a and b.

The function now has a real docstring because the string comes first.

Writing comments that repeat the code

Comments should add value. A comment that just repeats the line below it is noise and becomes stale quickly.

Problem: This comment does not explain anything new, so it adds clutter without helping the reader.

Python
count = 3
# Set count to 3.
print(count)
# Output: 3

Fix: Remove the obvious comment and keep only comments that explain intent, constraints, or unusual choices.

Python
count = 3
print(count)
# Output: 3

The corrected version is easier to read because every remaining comment adds information.

Letting docstrings drift away from the code

Documentation becomes wrong when behavior changes and the docstring does not. This is common after refactoring.

Problem: The function now returns a full name, but the docstring still says it returns only the first name.

Python
def format_name(first, last):
    """Return the first name only."""
    return f"{first} {last}"

print(format_name("Ada", "Lovelace"))
# Output: Ada Lovelace

Fix: Update the docstring so it matches the real behavior.

Python
def format_name(first, last):
    """Return the full name built from first and last."""
    return f"{first} {last}"

print(format_name("Ada", "Lovelace"))
# Output: Ada Lovelace

The corrected docstring matches the code, so readers and tools get the same answer.

When to Use Comments vs Docstrings vs Nothing

Use thisWhen it fitsExample
# commentExplain why the code is written a certain way or note a special case.# Use UTC because the API compares timestamps in UTC.
docstringDescribe the behavior of a module, class, function, or method for callers."""Return the number of items in stock."""
nothingThe code is already clear and extra words would repeat it.total = price + tax

When code is self-explanatory, skip the comment. Good code often needs fewer comments than beginners expect.

Comments and docstrings are not a substitute for clear names

A well-named function or variable reduces the need for explanations. Compare these two versions:

Python
def f(x):
    """Do something."""
    return x * 2

def double_price(price):
    """Return the doubled price."""
    return price * 2

The second version needs less explanation because the name already tells the reader what the function does.

Common Python Tools That Read Docstrings

Docstrings are useful because other Python features can display them automatically. help() shows documentation in the interactive interpreter. Editor tooltips often show the same text. Testing and introspection tools can also read __doc__.

Python
def miles_to_kilometers(miles):
    """Convert miles to kilometers."""
    return miles * 1.60934

print(miles_to_kilometers.__doc__)
# Output: Convert miles to kilometers.

This runtime visibility is the biggest difference from comments. A comment helps humans reading the source file. A docstring helps humans and tools that inspect the object later.

Try It Yourself

Write a small module that documents itself and shows the docstrings at runtime.

  • Add a module docstring that says what the file is for.
  • Define a function with a docstring that explains what it returns.
  • Call the function and print its result.
  • Print the function’s __doc__ value.

Expected output:

Python
18
Return the area of a rectangle.

Hint: Put the function docstring as the first statement inside the function body. Use multiplication to compute the area.

Show solution
Python
"""Simple rectangle utilities."""

def rectangle_area(width, height):
    """Return the area of a rectangle."""
    return width * height

print(rectangle_area(3, 6))
print(rectangle_area.__doc__)

Summary

  • Use # comments for explanations that help humans understand why code exists.
  • Use docstrings for modules, classes, functions, and methods that need runtime documentation.
  • Python stores a docstring only when it is the first statement in the object body.
  • Comments are ignored by Python; docstrings are available through __doc__ and help().
  • Do not write comments that only repeat the code.
  • Keep comments and docstrings accurate when the code changes.

Next, read about Python functions and how docstrings fit into reusable code design.