Introduction
In this lesson, you’ll learn how Python uses indentation to define code blocks instead of braces ({} and }). You’ll see how indentation controls the flow of your programs, how to structure common constructs like if statements, loops, and functions, and how to avoid (and fix) typical IndentationError issues. By the end, you’ll be able to use indentation both correctly and intentionally to make your code clean and readable.
Why Indentation Matters in Python
In many languages, code blocks are defined with braces:
if (x > 10) {
printf("Big number");
}
Python removes the braces and uses indentation to mark the start and end of blocks:
if x > 10:
print("Big number")
Everything at the same indentation level is part of the same block. When the indentation returns to a previous level, the previous block ends.
Key rules:
- A colon (
:) starts a new block (e.g., afterif,elif,else,for,while,def,class,try,except,finally). - The next line must be indented more than the line with the colon.
- Indentation must be consistent within the same block (same number of spaces or tabs — but never mix them).
Structuring if, elif, else Blocks
An if block in Python looks like this:
age = 17
if age < 13:
category = "child"
elif age < 18:
category = "teenager"
else:
category = "adult"
print("Category:", category)
# Output
Category: teenager
Explanation:
- Each condition line ends with
:and starts a new block. - The statements inside each block are indented exactly one level deeper.
elifandelseare aligned withifbecause they belong to the same decision structure.
Nested Conditional Blocks
You can nest if blocks by adding another level of indentation:
score = 92
if score >= 90:
grade = "A"
if score >= 95:
plus = "+"
else:
plus = ""
else:
grade = "B or below"
plus = ""
print("Final grade:", grade + plus)
# Output
Final grade: A-
Explanation:
- The inner
if score >= 95:block is indented two levels from the left margin. - Its
elseis aligned with that innerif, not the outer one.
Indentation in Functions and Loops
Functions with Indented Bodies
Function bodies are also code blocks defined by indentation:
def describe_number(n: int) -> str:
if n == 0:
return "zero"
elif n % 2 == 0:
return "even"
else:
return "odd"
result = describe_number(7)
print(result)
# Output
odd
Explanation:
- All lines inside
describe_numberare indented one level underdef describe_number(...):. - The
if,elif, andelseblocks are nested inside the function, so they have an extra level of indentation.
Loops with Nested Blocks
Loops work the same way:
numbers = [1, 2, 3, 4, 5, 6]
for n in numbers:
if n % 2 == 0:
print(n, "is even")
else:
print(n, "is odd")
# Output
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
Explanation:
- Code inside the
forloop is indented one level. - The
if/elseblocks are nested inside the loop, so they’re indented two levels from the left margin.
Deeply Nested Blocks: A Practical Example
This example combines a function, a loop, and conditionals, showing multiple indentation levels:
def filter_and_label_numbers(numbers):
labels = []
for n in numbers:
if n < 0:
label = "negative"
elif n == 0:
label = "zero"
else:
if n % 2 == 0:
label = "positive even"
else:
label = "positive odd"
labels.append((n, label))
return labels
items = filter_and_label_numbers([-2, -1, 0, 3, 4])
for number, label in items:
print(number, "->", label)
# Output
-2 -> negative
-1 -> negative
0 -> zero
3 -> positive odd
4 -> positive even
Explanation:
filter_and_label_numbersbody is indented once.for n in numbers:is inside the function, so one level.if,elif,elseinside the loop are one level deeper (two total from the left edge).- The inner
if n % 2 == 0:(for positive numbers) is three levels from the left margin. labels.append(...)is aligned with the outerifblock, so it runs for everyn.
This structure visually mirrors the program’s logic.
Common IndentationError Issues and How to Fix Them
Python raises IndentationError when your blocks don’t line up correctly.
1. Missing Indentation After a Colon
x = 10
if x > 5:
print("x is big") # Incorrect
This will raise:
IndentationError: expected an indented block
Fix: Indent the block after the if:
x = 10
if x > 5:
print("x is big") # Correct
2. Inconsistent Indentation Within the Same Block
Mixing different indentation widths (or tabs and spaces) causes errors:
value = 3
if value > 0:
print("positive")
print("still positive") # Extra spaces cause IndentationError
# Typical error
IndentationError: unexpected indent
Fix: Use the same number of spaces for all lines in the block:
value = 3
if value > 0:
print("positive")
print("still positive")
3. Misaligned elif / else
n = 5
if n > 10:
print("big")
else: # Incorrect alignment
print("not big")
# Typical error
IndentationError: unexpected indent
Fix: Align else (and elif) with the corresponding if:
n = 5
if n > 10:
print("big")
else:
print("not big")
Using Indentation to Improve Readability
Beyond avoiding errors, indentation should make your logic easy to see at a glance:
- Keep nesting shallow when possible. Deep nesting can be hard to read.
- Use indentation to group related logic and separate unrelated parts.
- When a block grows too complex, consider extracting parts into helper functions.
Example of refactoring for readability using indentation and functions:
def is_eligible_for_discount(age, is_student):
if age < 0:
return False
if age < 18:
return True
if is_student:
return True
return False
print(is_eligible_for_discount(16, False))
print(is_eligible_for_discount(25, True))
print(is_eligible_for_discount(30, False))
# Output
True
True
False
Explanation:
- Each decision is at the same indentation level, making the logic easy to follow.
- There’s no deep nesting, yet the flow is clearly defined by indentation.
Summary / Key Takeaways
In this lesson on Indentation and Code Blocks, you have learned:
- Indentation defines blocks in Python and replaces braces, so the interpreter relies on indentation levels to determine which statements belong together.
- Every colon (
:) must be followed by an indented block, and all statements in that block must share the same indentation level. if,elif, andelseblocks must be consistently aligned, withelifandelseat the same indentation as their correspondingifstatement.- Functions and loops contain indented bodies, and nested structures (like conditionals inside loops or functions) add additional indentation levels.
- Nested blocks visually represent program logic, making it easier to understand how decisions and iterations flow through your code.
- Common
IndentationErrors arise from missing or inconsistent indentation, such as failing to indent after a colon, misaligningelse, or mixing indentation widths. - Consistent indentation improves readability, allowing you and others to quickly grasp the structure of the code without tracing every line in detail.
- Good indentation practices support maintainable design, encouraging shallow nesting, clear grouping of logic, and sensible extraction into helper functions when blocks grow complex.
