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:
# 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.
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.
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.0This 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.
"""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.
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.
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.99The 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.
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: 10This 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.
"""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.
"""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 LovelaceThe 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.
x = 3
# x = 5
print(x)
# Output: 3The 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.
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.
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.
def area(radius):
"""Return the circumference of a circle."""
return 3.14159 * radius * radius
print(area(2))
# Output: 12.56636The 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?
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?
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.
def double_and_add_one(number):
"""Return number doubled and increased by one."""
return number * 2 - 1
print(double_and_add_one(4))
# Output: 7Show answer
The bug is the docstring. It says the function adds one, but the code subtracts one.
Fixed code:
def double_and_add_one(number):
"""Return number doubled and increased by one."""
return number * 2 + 1
print(double_and_add_one(4))
# Output: 9The 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.
def greet(name):
# Return a greeting for name.
return f"Hello, {name}!"
print(greet.__doc__)
# Output: NoneFix: Put a triple-quoted docstring as the first statement in the function.
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.
def add(a, b):
result = a + b
"""Return the sum of a and b."""
return result
print(add.__doc__)
# Output: NoneFix: Move the docstring to the top of the function body.
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.
count = 3
# Set count to 3.
print(count)
# Output: 3Fix: Remove the obvious comment and keep only comments that explain intent, constraints, or unusual choices.
count = 3
print(count)
# Output: 3The 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.
def format_name(first, last):
"""Return the first name only."""
return f"{first} {last}"
print(format_name("Ada", "Lovelace"))
# Output: Ada LovelaceFix: Update the docstring so it matches the real behavior.
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 LovelaceThe corrected docstring matches the code, so readers and tools get the same answer.
When to Use Comments vs Docstrings vs Nothing
| Use this | When it fits | Example |
|---|---|---|
| # comment | Explain why the code is written a certain way or note a special case. | # Use UTC because the API compares timestamps in UTC. |
| docstring | Describe the behavior of a module, class, function, or method for callers. | """Return the number of items in stock.""" |
| nothing | The 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:
def f(x):
"""Do something."""
return x * 2
def double_price(price):
"""Return the doubled price."""
return price * 2The 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__.
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:
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
"""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.