PYTHON / GETTING STARTED
Comments and docstrings
Write comments that explain why code is the way it is, and docstrings that your program and tools can read back at runtime.
What you will learn
- Use # for notes the interpreter throws away before running the code
- Place a string literal as the first statement to create a __doc__ value
- Read any object's documentation with obj.__doc__ or inspect.getdoc(obj)
- Tell apart a real docstring from a triple-quoted string that is merely an expression
Understanding Comments and docstrings
A comment starts at a # and runs to the end of the line. Python's tokenizer drops comments before the compiler ever sees them, so a comment has no runtime representation at all: nothing in the compiled bytecode, no attribute you can query, no cost when the line executes. Python has no /* ... */ block comment form either, so a multi-line note is just several # lines in a row.
A docstring is not a comment. It is an ordinary string literal that happens to be the first statement in a module, class, or function body, and the compiler reacts to that position by storing it as the object's __doc__ attribute. That is why help(len) works in a REPL where no source file is available, and why editors can show a tooltip for a function imported from a compiled package: they read the attached string, not the file on disk. Move that string one line down, below an assignment or an import, and it stops being a docstring and becomes a discarded expression, with __doc__ set to None.
The split follows from who reads each one. A docstring is the public contract of the object, so it says what the function returns, what the arguments mean, and what it raises, phrased for someone who will never open your file. A comment is a private aside for whoever edits the line beneath it, so it should carry the reason, the constraint, or the surprising input that forced the code into its current shape. A comment that restates what the code obviously does will not be updated when the code changes, and then it actively lies.
def celsius_to_fahrenheit(c):
"""Convert a Celsius temperature to Fahrenheit.
The offset is applied after scaling, which is why 0 C maps to 32 F.
"""
# 9 / 5 is true division, so the result is a float even for int input.
return c * 9 / 5 + 32
print(celsius_to_fahrenheit(100))
print(celsius_to_fahrenheit.__doc__.splitlines()[0])
print(celsius_to_fahrenheit.__doc__ is None)
A comment is deleted before your program runs, while a docstring survives as data attached to the object.
Worked examples
Three functions, one docstring
Shows that only a string in first-statement position becomes __doc__.
def a():
# This reads like documentation but it is a comment.
return 1
def b():
"One-line docstring."
return 2
def c():
x = 3
"Too late to be a docstring."
return x
print(a.__doc__)
print(b.__doc__)
print(c.__doc__)
Example explained
Line 1a has no docstring because its comment was removed before compilation, so __doc__ defaults to None.
Line 2b uses single quotes, which is fine: quote style is irrelevant, position is what matters.
Line 3In c the assignment x = 3 comes first, so the string is evaluated, thrown away, and __doc__ stays None.
Module docstring
Demonstrates that a file's own docstring is available as the global name __doc__.
"""Tiny geometry helpers."""
import math
def circle_area(r):
"""Return the area of a circle with radius r."""
return math.pi * r ** 2
print(__doc__)
print(circle_area.__doc__)
print(round(circle_area(2), 4))
Example explained
Line 1The first line is the module docstring, so Python binds it to the module global __doc__ before running anything else.
Line 2__doc__ is readable without importing anything because every module carries it.
Line 3The import on line 3 is allowed to follow the docstring; only code placed above the string would disable it.
Indentation inside a long docstring
Compares the raw __doc__ text with the dedented version inspect.getdoc produces.
import inspect
def clamp(x, low, high):
"""Return x limited to the range [low, high].
Args:
x: the value to clamp.
low: lower bound, returned when x < low.
high: upper bound, returned when x > high.
"""
return max(low, min(x, high))
print(repr(clamp.__doc__.splitlines()[2]))
print(repr(inspect.getdoc(clamp).splitlines()[2]))
print(clamp(15, 0, 10))
Example explained
Line 1__doc__ keeps the source indentation verbatim, so the continuation lines start with four spaces.
Line 2inspect.getdoc strips the common leading whitespace from every line after the first, which is what help() displays.
Line 3The summary line sits on the same line as the opening quotes, a convention that keeps the first line usable on its own.
Important notes
Comments are not statements, so a # line placed above the docstring inside a function body is harmless; the string still counts as the first statement.
Running python with -OO strips docstrings out of the bytecode and __doc__ becomes None, so never make program logic depend on the text of a docstring.
Common mistakes
Writing the description in # lines above the def instead of inside it: help() and editor tooltips show nothing, because there is no string for them to read.
Slipping an import or a debug print above the docstring inside a function, which silently demotes the string to a dead expression and leaves __doc__ as None.
Using a triple-quoted string to disable a block of code: it is still compiled and evaluated as an expression, and if it lands in first-statement position it quietly becomes the docstring.
Try it yourself
Change, predict, then run
Write a function is_leap_year(year) with a docstring whose first line explains the return value and whose body has one # comment justifying the 400-year rule, then print is_leap_year.__doc__ and is_leap_year(1900).
Open the Python workspaceCheck your understanding
You import a function from a package that ships only compiled .pyc files, with no .py source anywhere on disk. help() still prints its description. Why?
- The description is a string literal the compiler stored on the function object as __doc__, whereas comments were discarded by the tokenizer
- Comments are preserved in the .pyc file too, and help() decompiles them on demand
- help() locates the original source file and re-reads the comment block above the def
- Comments are only discarded when a file is run directly, not when it is imported as a module
Show answer
Documentation survives because a docstring is real data attached to the object, so it travels inside the compiled file. Option 3 is tempting because help() does show source-like text, but there is no source file here, and help() equally works on functions you typed into the REPL; comments never reach the compiler at all, in any execution mode.