003. Indentation
Block structure is visible structure
003. Indentation
Aryan writes a loop to sum up memory usage across a list of processes. Coming from C, he’s used to braces marking blocks — indentation was just cosmetic. In Python, it’s the grammar itself.
He pastes from a C snippet and the accumulation line lands one level too far left:
for proc in processes:
if proc["mem"] > 0:
pass # valid process
total += proc["mem"] # <-- runs ONCE after the loop, not each iteration!The code runs silently. No error. But total only reflects the last process. Every other process’s memory is ignored.
This is one of the most common Python bugs for C/Java developers. The fix is a single indent — but understanding WHY is the lesson.
💡 Fun fact: Python’s use of indentation as syntax was inspired by the ABC language (1987). Guido van Rossum worked on ABC before creating Python and carried over the idea that forcing consistent indentation makes code structure immediately visible without braces.
⚠️ Watch out: The most dangerous indentation bug is silent — Python does not always raise IndentationError. A line can be at the wrong scope level and still be valid syntax, producing wrong results with no error message, as Aryan’s total bug shows.
🤔 Think about it: Python forces you to indent correctly, while C only recommends it. Does mandatory indentation make Python code easier to read, or does it just make certain classes of bugs impossible?
Learning objectives
- Understand that indentation defines code blocks in Python
- Identify lines that run inside vs outside a loop
- Use 4-space indentation consistently
Key concepts
- indentation
- code blocks
- for loop
Try it
Concept detail
Python uses indentation instead of curly braces {} to define code blocks. Every line inside a for, if, def, or class must be indented consistently. PEP 8 recommends 4 spaces per level. Mixing tabs and spaces causes TabError.
The broken_code bug is semantic, not syntactic: an extra line modifies total AFTER the loop completes, subtracting 100 from a correct sum. The code runs without errors but produces the wrong answer (655 instead of 755).
This teaches a subtle but important lesson: Python indentation bugs don’t always produce IndentationError — code can be syntactically valid but logically wrong because a line is at the wrong scope level. Read loops by asking: which lines run on every iteration, and which run only once at the end?
Solution
process_memory = [120, 340, 85, 210]
total = 0
for mem in process_memory:
if mem > 0:
total += memTests
def test_total_all_processes():
assert total == 755
def test_process_memory_unchanged():
assert process_memory == [120, 340, 85, 210]
def test_total_is_int():
assert type(total) == int