PYTHON • SOFTWARE CRAFT AND COMMUNICATION

Docstrings & Comments — Add meaningful docstrings and comments

Clear documentation turns cryptic code into a story anyone can follow.

Historical Context & Motivation

From the very first days of computing, programmers realized that writing code is only half the battle — someone else (or even your future self) has to read that code later. Early programming languages like FORTRAN (1957) allowed programmers to insert comment lines so that human readers could understand what the machine instructions were doing. Without comments, revisiting a program after even a few weeks felt like deciphering a secret language.

As software projects grew from hundreds to millions of lines, the need for structured, machine-readable documentation became urgent. Languages began introducing docstrings — special strings embedded directly in source code that tools could extract automatically. Python, created by Guido van Rossum in 1991, embraced this idea early on, making docstrings a first-class feature of the language. Today, every serious Python project relies on both comments and docstrings to keep code understandable and maintainable.

1957
FORTRAN Comment Lines
FORTRAN introduces the C character in column 1 to mark a line as a comment, establishing the tradition of inline documentation.
1991
Python Is Born
Guido van Rossum releases Python 0.9.0. The language uses the # symbol for comments and triple-quoted strings that will later become docstrings.
2001
PEP 257 — Docstring Conventions
Python Enhancement Proposal 257 formalizes how docstrings should be written, covering one-liners, multi-line docstrings, and placement rules.
2010s
Auto-Doc Tools Mature
Tools like Sphinx and pdoc generate professional HTML documentation directly from docstrings, proving that well-written docstrings pay off in real-world projects.
2020s
AI-Powered Code Assistants
Modern code editors use docstrings to power autocomplete, inline hints, and AI suggestions, making documentation even more valuable.

So here is the central question this lesson addresses: how do you write comments and docstrings that are genuinely meaningful — adding clarity without cluttering your code? Let's find out.

Core Principles & Definitions

Before diving into syntax, it helps to understand the two distinct tools Python gives you for documenting code. A comment is a note for humans that Python ignores entirely — it starts with # and extends to the end of the line. A docstring is a special string literal placed as the very first statement inside a module, class, method, or function. Unlike comments, Python actually stores docstrings so that tools and the built-in help() function can access them at runtime.

1

Comments Explain "Why"

Good comments explain the reasoning behind a decision — the why, not the what. The code itself shows what happens; comments reveal intent.
2

Docstrings Explain "What" & "How"

Docstrings describe what a function, class, or module does and how to use it. They serve as the public-facing user manual for your code.
3

Don't Repeat the Code

A comment that simply restates the code is noise. # add 1 to x above x += 1 wastes the reader's time.
4

Keep It Current

Outdated documentation is worse than none at all. When you change the code, update the comments and docstrings to match.
5

Follow PEP 257

Python's official style guide (PEP 257) defines standard formatting for docstrings. Consistency makes every project easier to navigate.
✦ KEY TAKEAWAY
Think of comments like sticky notes you leave on a recipe — they explain tricky steps or why you substituted an ingredient. Docstrings are more like the recipe's title, ingredient list, and serving instructions printed on the card itself. Both are essential, but they serve different audiences and purposes.

Visual Explanation — Anatomy of a Documented Function

The diagram below breaks down a well-documented Python function, labeling every part so you can see exactly where comments and docstrings belong and how they differ in purpose.

This diagram shows a complete, well-documented function. Notice how the comment above the function explains why the function exists, while the docstring inside it explains what it does and how to use it.

Look at how each piece of documentation has a clear job. The green comment at the top gives context about the project (a weather app). The violet docstring follows PEP 257 format: a one-line summary, then sections for Args and Returns. The second green comment clarifies the math formula for anyone skimming the code quickly. Together, they make the function self-explanatory.

How Comments & Docstrings Work Under the Hood

Understanding the difference between comments and docstrings becomes easier when you know what Python actually does with each one. A comment is stripped away by the Python interpreter before any code runs. It is truly invisible to the program. A docstring, on the other hand, is stored as an attribute called __doc__ on the object it belongs to. This means you can access it at runtime, which is what help() and documentation generators rely on.

Comment Syntax

In Python, everything from the # symbol to the end of that line is a comment. Python does not have a built-in multi-line comment syntax like some languages (e.g., /* ... */ in Java). To write multi-line comments, you simply put # at the start of each line.

Docstring Syntax

A docstring uses triple quotes — either """triple double quotes""" or '''triple single quotes'''. By convention, double quotes are preferred. The docstring must be the very first statement inside a function, class, or module for Python to recognize it as the __doc__ attribute. If you place it anywhere else, it is just a regular string that gets ignored.

Accessing Docstrings at Runtime

You can read any object's docstring using print(my_function.__doc__) or by calling help(my_function) in the Python interactive shell. This is incredibly useful — imagine being able to look up a recipe just by asking the oven what it can cook. That is effectively what docstrings give you: built-in, always-available instructions.

This flowchart shows that comments are discarded during parsing, while docstrings are stored as the __doc__ attribute and can be retrieved with help().

Types of Documentation & Style Conventions

Not all comments and docstrings are created equal. Understanding the different types helps you choose the right tool for each situation. Let's classify them and compare the most popular docstring formats.

Types of Comments

Common comment types in Python
TypeExampleWhen to Use
Block comment# Retry up to 3 times because the API is flakyBefore a block of code to explain a non-obvious decision
Inline commentx = x + 1 # compensate for 0-based indexAfter a line to clarify a single tricky expression
TODO comment# TODO: add input validationTo mark planned improvements that you haven't implemented yet

Docstring Formats Compared

Several popular docstring styles exist. The three most common are Google style, NumPy/SciPy style, and reStructuredText (reST) style. Pick one style and use it consistently throughout your project.

Google vs. NumPy docstring styles
FeatureGoogle StyleNumPy Style
Parameters headingArgs:Parameters ----------
Return headingReturns:Returns -------
ReadabilityCompact and clean — great for short functionsSpacious — ideal for complex scientific functions
Common inGeneral Python, web apps, startupsData science, machine learning libraries
💡 Pro Tip
For high school projects, the Google style is the easiest to read and write. Use headings like Args:, Returns:, and Raises: followed by indented descriptions.

Worked Example — Documenting a Student Gradebook Function

Let's walk through the process of writing documentation for a function that calculates a student's letter grade. We will start with undocumented code and transform it step by step into a well-documented piece of software.

Documenting calculate_grade()
1
Step 1 — Start With the Bare FunctionHere is the raw function with no documentation at all: def calculate_grade(scores): avg = sum(scores) / len(scores) if avg >= 90: return 'A' elif avg >= 80: return 'B' elif avg >= 70: return 'C' elif avg >= 60: return 'D' else: return 'F' This works, but anyone reading it has to figure out what scores should be, what the function returns, and what scale it uses.
2
Step 2 — Add the Docstring Summary LineThe first line of a docstring should be a brief, complete sentence that summarizes the function's purpose. It should fit on one line. """Calculate a letter grade from a list of numeric scores."""
Summary: one sentence describing what the function does.
3
Step 3 — Add Args and Returns SectionsNext, list each parameter with its expected type and a short description. Then describe the return value. """Calculate a letter grade from a list of numeric scores. Args: scores (list[float]): A list of numeric test scores (each between 0 and 100). Returns: str: A single letter grade ('A', 'B', 'C', 'D', or 'F'). """
Args and Returns sections now tell the user exactly what to pass in and what to expect back.
4
Step 4 — Add a Clarifying Comment for the Grading ScaleThe grading thresholds are a design decision. A comment explains why these particular numbers were chosen. # Using standard 10-point grading scale (A=90+, B=80+, etc.)
The comment justifies the choice of thresholds without repeating the code.
5
Step 5 — Final Documented FunctionPutting it all together: def calculate_grade(scores): """Calculate a letter grade from a list of numeric scores. Args: scores (list[float]): A list of numeric test scores (each between 0 and 100). Returns: str: A single letter grade ('A', 'B', 'C', 'D', or 'F'). """ avg = sum(scores) / len(scores) # Using standard 10-point grading scale (A=90+, B=80+, etc.) if avg >= 90: return 'A' elif avg >= 80: return 'B' elif avg >= 70: return 'C' elif avg >= 60: return 'D' else: return 'F'
Now anyone can call help(calculate_grade) and immediately know what it does, what it needs, and what it returns.

Good vs. Bad Documentation — Strengths & Pitfalls

Writing documentation is a skill, and like any skill, there are common mistakes. The table below contrasts effective documentation with problematic documentation so you can recognize the difference instantly.

Common documentation pitfalls and their fixes
❌ Bad Practice✅ Good PracticeWhy It Matters
# increment x x += 1# Off-by-one fix: API uses 1-based indexing x += 1The bad comment restates the code. The good comment explains the reason.
def f(a, b): """Function."""def add_scores(current, new): """Add new scores to the current total."""Vague names and docstrings force the reader to read every line of code.
No docstring at all on a public functionAt minimum, a one-line docstring summarizing purposeWithout a docstring, help() returns nothing useful.
Outdated comment that contradicts the codeUpdated comment that matches current behaviorMisleading docs create bugs and waste debugging time.
Commenting every single lineCommenting only where intent is non-obviousOver-commenting clutters the code and makes real comments hard to spot.
✦ KEY TAKEAWAY
Imagine you're writing directions to your house for a friend. You wouldn't say "turn the steering wheel 90 degrees clockwise" — that's restating the obvious. You'd say "turn right at the gas station because GPS sometimes routes you through the construction zone." Good comments work the same way: they share the reasoning, not the mechanics.

Connection to Advanced Practices

Once you're comfortable writing comments and docstrings, you'll encounter more advanced documentation practices in professional Python development. These build directly on what you've learned.

From basics to advanced documentation practices
What You Know NowWhat Comes NextHow They Connect
Describing parameter types in docstringsType hints — def greet(name: str) -> str:Type hints formalize what docstrings describe informally, letting tools catch errors automatically.
Writing one-line summaries of functionsSphinx auto-documentationSphinx reads your docstrings and generates a full website of documentation — the better your docstrings, the better the website.
Using examples in docstringsDoctests — >>> add(2, 3) 5Python's doctest module can run the examples in your docstrings as actual tests, ensuring your docs stay accurate.
Commenting "why" for tricky codeArchitecture Decision Records (ADRs)In large projects, teams write formal documents explaining major design decisions — like comments, but at a project level.

As you move into AP Computer Science, college courses, or open-source projects, these advanced techniques will feel like natural extensions of the habits you're building now. Every professional Python developer writes docstrings — the skill you're learning today is one you'll use for the rest of your programming career.

Practice Problems

PROBLEM 1 — CONCEPTUAL
What is the fundamental difference between a comment and a docstring in Python? Explain what happens to each one when the Python interpreter runs your code.
PROBLEM 2 — BASIC
Write a proper Google-style docstring for the following function: def area_of_circle(radius): return 3.14159 * radius ** 2
PROBLEM 3 — INTERMEDIATE
The following code has three comments. Identify which comments are helpful and which are redundant or misleading, then rewrite the problematic ones: # This function adds two numbers def calculate_bmi(weight_kg, height_m): # calculate bmi bmi = weight_kg / (height_m ** 2) # WHO classifies BMI >= 30 as obese if bmi >= 30: return 'obese' return 'not obese'
PROBLEM 4 — APPLIED
You are building a library checkout system. Write a fully documented function called is_overdue that takes a due_date (string in 'YYYY-MM-DD' format) and returns True if today's date is past the due date. Include a docstring with Args, Returns, and an Example section, plus at least one meaningful comment in the code body.
PROBLEM 5 — CRITICAL THINKING
A classmate argues: "If I write clean code with good variable names, I don't need any comments or docstrings." Write a thoughtful response that addresses this claim. Include at least two specific scenarios where even clean code benefits from documentation, and one scenario where a comment might genuinely be unnecessary.

Lesson Summary

Python gives you two tools for documentation: comments (lines starting with #) and docstrings (triple-quoted strings placed as the first statement in a function, class, or module). Comments are discarded by the interpreter and exist only in source code, while docstrings are stored at runtime as the __doc__ attribute and accessible via help(). Comments should explain why code works a certain way, while docstrings describe what a function does and how to use it.

Follow PEP 257 conventions and choose a consistent style like Google style with Args: and Returns: sections. Avoid the three big pitfalls: restating obvious code, leaving docs outdated, and over-commenting every line. As you advance, docstrings connect directly to type hints, auto-documentation tools, and doctests — making today's habit one of the most valuable skills in professional Python development.

Varsity Tutors • Python • Docstrings & Comments — Add meaningful docstrings and comments