Indentation and Code Blocks
Concepts covered: Conditionals
In most programs, some lines run only when a condition holds, some run again and again, and some wait until they are called by name. Python decides which lines belong to such a group by looking at how far each line is indented. A header line ends with a colon, and every line indented beneath it is part of the header's block. The block ends at the first line that steps back to the header's own indentation.
balance = 120
price = 150
if price > balance:
print("not enough money")
print("short by", price - balance)
print("checkout finished")if runs its block only when the expression after it is True. Here price > balance is True, so both indented prints run, and then line 6 runs because it was never inside the block. Swap the numbers so the condition is False and the indented lines are skipped, while line 6 still runs. Now watch what one change in spacing does to the same 6 lines.
balance = 200
price = 150
if price > balance:
print("not enough money")
print("short by", price - balance)
print("checkout finished")Output:
short by -50 checkout finished
Line 5 lost its 4 spaces, so it left the block. It now runs on every checkout and reports a negative shortfall to a customer who has plenty of money. The text of the program changed by 4 characters and the program's meaning changed completely, which is why Python treats indentation as part of the code.
What does this program print?
score = 40
if score > 50:
print("pass")
score = score + 10
print(score)- 40, because the condition is False and only the final print is outside the block
- pass, then 50, because every line after the if belongs to it
- 50, because the addition on line 4 is at a different level from the print above it
- pass, then 40, because print runs before the condition is checked
The 3 headers you will meet most
Each ends with a colon and owns the indented lines under it
- if price > 100: runs its block once, and only when the expression is True
- for i in range(5): runs its block once per value, with i holding the current one each pass
- def total(price): names its block and runs none of it now; the block runs each time total(...) is called later
Each header gets a lesson of its own later. What matters here is the shape they share: a colon, then an indented block, then a return to the left margin. Press play on the loop below and watch the single indented line run 5 times while the header hands i a new value on each pass.
for i in range(5):
print(i)0 1 2 3 4
A def block differs in timing. When the file runs past line 1, Python stores the 2 indented lines under the name calculate_total and runs none of them. They run on line 5, when the name is called with 100 and 0.08, and the result 108.0 travels back to be stored in result and printed.
def calculate_total(price, tax_rate):
total = price * (1 + tax_rate)
return total
result = calculate_total(100, 0.08)
print(result)108.0
Blocks inside blocks
A block can hold another header, which opens a deeper block one level further in. Each level is, by convention, 4 more spaces; Python requires only that every line of one block is indented the same amount. In the program below, ask of every line which header owns it. Lines 4 and 5 sit 8 spaces in, so they belong to the if, which itself belongs to the for. Line 6 sits 4 spaces in, belongs to the for alone and runs on every pass. Line 7 is back at the margin and runs once, after the loop has finished all 4 passes.
count = 0
for i in range(4):
if i > 1:
count = count + 1
print("counted", i)
print("checked", i)
print("total", count)checked 0 checked 1 counted 2 checked 2 counted 3 checked 3 total 2
Indentation errors that stop the program
Python does not guess at a block's borders, so 3 mistakes stop the program before any line runs. A header with nothing indented under it, and a line indented where no header asked for it, each raise an IndentationError. Indenting some lines of one block with a tab and others with spaces raises a TabError, because a tab and 4 spaces look identical on screen and differ to the interpreter. Each report names the line, so open the file at that line and count the spaces.
| What you wrote | Error | Message |
|---|---|---|
| if 3 > 2: followed by print("yes") at the margin | IndentationError | expected an indented block |
| print("hi") pushed in 4 spaces after a plain line, with no header above it | IndentationError | unexpected indent |
| one line of a block indented with a tab, the other lines of that block with spaces | TabError | inconsistent use of tabs and spaces in indentation |
- Do
- Indent with 4 spaces per level, every time
- End every header line with a colon
- Set your editor to insert spaces when you press Tab
- Return to the margin to close a block
- Avoid
- Mix tabs and spaces in one file
- Indent a line that no header asked for
- Use 2 spaces in one block and 4 in another
- Expect a blank line to end a block; only dedenting does
Practice
About this lesson
This section is part of the Python Foundations: Intermediate lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.