Python Comments
Learn how to add comments to your Python code for better documentation and readability.
Creating a Comment
Comments can be used to explain Python code, make the code more readable, or prevent execution when testing code.
Comments start with a #, and Python will ignore them:
Example
# This is a comment
print("Hello, World!")Comments can be placed at the end of a line, and Python will ignore the rest of the line:
Example
print("Hello, World!") # This is a commentA comment does not have to be text that explains the code, it can also be used to prevent Python from executing code:
Example
# print("Hello, World!")
print("Cheers, Mate!")Multiline Comments
Python does not really have a syntax for multiline comments. To add a multiline comment you could insert a # for each line:
Example
# This is a comment
# written in
# more than just one line
print("Hello, World!")Or, not quite as intended, you can use a multiline string. Since Python will ignore string literals that are not assigned to a variable, you can add a multiline string (triple quotes) in your code, and place your comment inside it:
Example
"""
This is a comment
written in
more than just one line
"""
print("Hello, World!")As long as the string is not assigned to a variable, Python will read the code, but then ignore it, and you have made a multiline comment.
Best Practices for Comments
- Use comments to explain why something is done, not just what is done
- Keep comments concise and relevant
- Update comments when you change the code
- Use proper grammar and spelling in comments
- Avoid obvious comments that don't add value
Good Comment Example
# Calculate compound interest using the formula A = P(1 + r/n)^(nt)
amount = principal * (1 + rate/frequency) ** (frequency * time)Poor Comment Example
# Add 1 to x
x = x + 1Comments vs Docstrings
A # comment explains code to other programmers. A docstring — a string literal as the first line of a module, function, or class — documents what something does and is readable at runtime via help() or .__doc__.
def area(radius):
"""Return the area of a circle with the given radius."""
return 3.14159 * radius ** 2
print(area.__doc__) # Return the area of a circle with the given radius.Good vs Noisy Comments
| Avoid (restates code) | Prefer (explains why) |
|---|---|
i += 1 # add 1 to i | i += 1 # skip the header row |
x = x * 2 # double x | x = x * 2 # bytes -> bits |
Multi-line explanations use several # lines. Triple-quoted strings that are not docstrings are still executed as (unused) string objects — use # for real comments.
Try It Yourself
Exercise 1: Add a comment that explains why the line runs, not what it does: price = price * 0.9.
Show solution
price = price * 0.9 # apply the 10% loyalty discountExercise 2: Write a function greet with a one-line docstring, then print its docstring.
Show solution
def greet(name):
"""Return a friendly greeting for name."""
return f"Hello, {name}!"
print(greet.__doc__)Key Takeaways
#starts a comment to the end of the line.- Explain why, not what — the code already shows what.
- Use docstrings to document functions, classes, and modules.
📘 Real-World Deep Dive
PEP 8 / PEP 257 set a small, useful set of commenting conventions. Combined with docstrings + type hints, comments turn a "working script" into a "maintainable module".
Real-Life Scenario
A small module that parses a domain-specific file format. Docstrings document the contract, type hints enforce it, and inline comments explain non-obvious choices.
Real-Life Example
"""Lightweight INI-style config parser.
Supports sections, comments starting with '#', and key=value lines.
Lines are trimmed of leading/trailing whitespace and bare comments.
"""
from __future__ import annotations
import re
from pathlib import Path
from typing import Iterator
SECTION_RX = re.compile(r"^\[(?P<name>[^\]]+)\]$")
def parse(text: str) -> dict[str, dict[str, str]]:
"""Parse text into a nested dict of section, key, value."""
sections: dict[str, dict[str, str]] = {"__default__": {}}
current = sections["__default__"]
for raw in text.splitlines():
line = raw.strip()
if not line or line.startswith("#"):
continue # skip blanks / comments
m = SECTION_RX.match(line)
if m:
current = sections.setdefault(m["name"].strip(), {})
continue
# key/value inside a section
if "=" not in line:
continue # tolerate malformed lines
key, _, value = line.partition("=")
current[key.strip()] = value.strip().strip('"')
return sections
ini_text = Path("config.ini").read_text(encoding="utf-8")
cfg = parse(ini_text)
print(cfg["db"]["host"], cfg["db"]["port"])Expected Output
localhost 5432Common mistakes
- Comments that re-state the obvious code are noise; explain *why* in plain English.
- Stale comments are an active liability — keep them in sync with the code.
- Triple-quoted strings as docstrings belong at the top of modules, classes, and methods; not as block comments.
🚀 Performance & Best Practices
- Keep comments on their own line above the code; trailing comments hurt diff readability.
- Docstrings at module/class/function level carry real weight —
pydocstyleenforces them. - For algorithms, prefer ASCII diagrams in comments over paragraphs of prose.
🧪 Try It Yourself
- Wire
docstring_parserinto a test suite to catch missing docstrings. - Refactor
parse()to a generator that yields events; document each. - Add support for inline comments (
key = value # note).