Python Comments — Single-line, Multi-line & Best Practices
Learn how to write single-line and multi-line comments in Python, when to use docstrings, inline comments, and comment best practices with examples.
Comments are lines in your source code that Python's interpreter ignores completely. They exist for human readers — to explain intent, document decisions, and flag issues — without affecting how the program runs. This chapter covers every kind of Python comment, when to use each one, and the conventions that keep large codebases readable.
Single-line comments
A single-line comment starts with a hash character (#). Everything from the # to the end of that line is ignored by the interpreter.
# Calculate the area of a circle
radius = 5
area = 3.14159 * radius ** 2
print(area) # outputs 78.53975The comment on the last line — placed after executable code on the same line — is called an inline comment. Use them sparingly; reserve them for genuinely non-obvious logic rather than restating what the code already says.
When to use single-line comments
- Explain why a decision was made, not what the code does (the code shows the what).
- Mark temporary workarounds:
# TODO: replace with database lookup. - Disable a single line temporarily during debugging.
# FIXME: division by zero if user_count is 0
average = total_score / user_countMulti-line comments
Python has no dedicated multi-line comment syntax the way C has /* ... */. The idiomatic way to span several lines is to use consecutive single-line comments, each starting with #.
# This function converts a temperature in Celsius to Fahrenheit.
# The formula is: F = (C * 9/5) + 32
# Returns a float rounded to two decimal places.
def celsius_to_fahrenheit(c):
return round((c * 9 / 5) + 32, 2)
print(celsius_to_fahrenheit(100)) # 212.0
print(celsius_to_fahrenheit(0)) # 32.0Most Python editors and IDEs let you select multiple lines and toggle # on all of them at once (usually Ctrl+/ or Cmd+/).
Docstrings — structured documentation comments
Python has a special string literal convention called a docstring (short for documentation string). A docstring is a triple-quoted string placed immediately after a def, class, or module header. Although technically a string expression, not a comment, it serves as the standard documentation mechanism and is accessible at runtime via the __doc__ attribute.
def greet(name):
"""Return a personalised greeting message.
Args:
name (str): The name of the person to greet.
Returns:
str: A greeting string.
"""
return f"Hello, {name}!"
print(greet("Alice")) # Hello, Alice!
print(greet.__doc__) # prints the docstring aboveTriple-quoted strings as block comments
Because Python discards string literals that are not assigned to anything, a triple-quoted string sitting by itself (not in a def/class position) is sometimes used as an informal block comment:
"""
This script processes the daily sales report.
It reads from sales.csv, aggregates by region,
and writes a summary to report.txt.
"""
import csvThis pattern works but has a subtle cost: unlike # comments, the interpreter does parse the string and may keep it in the compiled bytecode. For module-level documentation, prefer a proper module docstring (the very first statement in the file). For other multi-line explanations inside functions, stick with consecutive # lines.
Commenting out code during debugging
Temporarily disabling code with comments is a common debugging technique:
def calculate_discount(price, rate):
# discount = price * rate # old flat-rate formula
discount = price * rate if rate < 1 else price * (rate / 100)
return price - discount
print(calculate_discount(100, 0.2)) # 80.0
print(calculate_discount(100, 20)) # 80.0Once you have confirmed the fix, remove the commented-out lines rather than leaving them in the codebase permanently — stale commented code confuses future readers.
Special comment directives
Python and its tooling recognise a few comment lines that carry machine-readable meaning:
The shebang line
On Unix-like systems, the first line of a script can specify the interpreter:
#!/usr/bin/env python3
# This line tells the OS to run the file with python3.
print("Hello from a standalone script!")This line is a comment as far as Python is concerned (it starts with #), but the OS uses it when the file is executed directly (./script.py).
Encoding declaration
If your source file uses a character encoding other than UTF-8 (the default since Python 3), declare it on the first or second line:
# -*- coding: utf-8 -*-Python 3 defaults to UTF-8, so this is rarely needed today, but you may encounter it in legacy code.
Type-checker directives
Type checkers such as mypy respect special inline comments:
x = [] # type: ignore
result = some_function() # type: ignore[return-value]These suppress specific type errors without changing runtime behaviour. See the Python Variables chapter for more on how Python handles types.
Comment best practices
Following these conventions will make your comments genuinely useful:
| Practice | Good example | Avoid |
|---|---|---|
| Explain why, not what | # cache result to avoid redundant API calls | # set x to 5 |
| Keep comments up to date | Update the comment when you change the code | Leaving stale comments that contradict the code |
| Use complete sentences | # Skip empty lines before processing. | # skip empty |
One space after # | # This is correct | #This has no space |
| Avoid obvious comments | (no comment needed) | x = x + 1 # add 1 to x |
PEP 8 — Python's official style guide — recommends:
- Inline comments should be separated from the statement by at least two spaces.
- Each inline comment should start with
#(hash, then one space). - Block comments that apply to the code below them should be indented to the same level.
def apply_tax(price, tax_rate):
# Tax rate is expressed as a decimal (e.g., 0.07 for 7 %).
# Prices must be non-negative; validation happens upstream.
tax = price * tax_rate
return price + tax # total including taxCommon mistakes to avoid
1. Leaving TODO comments without tracking them
# TODO: handle the case where the file does not exist
data = open("data.txt").read()TODOs are useful during development but should be linked to an issue tracker, not left indefinitely in production code.
2. Commenting out large blocks instead of deleting them
Version control (git) preserves history. There is no need to keep commented-out code for posterity — delete it and rely on git log if you ever need it back.
3. Inconsistent style
Mix of #comment, # comment, and ## comment in the same file makes the codebase feel unowned. Agree on a style and apply it consistently.
Summary
| Comment type | Syntax | Use for |
|---|---|---|
| Single-line | # text | Inline notes, section headers |
| Multi-line | Consecutive # lines | Extended explanations |
| Docstring | """text""" after def/class | Public API documentation |
| Shebang | #!/usr/bin/env python3 | Unix script entry point |
| Encoding | # -*- coding: utf-8 -*- | Non-UTF-8 source files |
| Type ignore | # type: ignore | Suppress mypy errors |
Comments are a lightweight tool that pay dividends whenever another developer (or future you) reads your code. For deeper reading on adjacent topics, see Python Syntax and Python Variables.