Python Syntax & Indentation
Every programming language needs a way to say "this group of statements belongs together." Languages like C, Java, and JavaScript wrap those groups in curly braces: a backtrace-style block like if (x) { doThing(); doOtherThing(); }. Python takes a completely different approach — it uses indentation itself to define blocks. There are no braces to open or close. The whitespace at the start of a line is not just cosmetic; it is part of the language's grammar.
Indentation instead of braces
In brace-based languages, indentation is a courtesy to human readers — the compiler does not care whether you indent at all. You could write an entire program on one line (ignoring style guides and your teammates' patience) and it would still run. Python removes that option entirely. The interpreter uses indentation to know where a block of code starts and ends, so consistent whitespace is not a style preference — it is required syntax.
def greet(name):
if name:
print(f"Hello, {name}!")
else:
print("Hello, stranger!")
greet("Ava")
greet("")Hello, Ava! Hello, stranger!
Notice that there are no braces anywhere in that function. The body of greet is everything indented one level under the def line; the body of the if is everything indented one level further under it. Remove the indentation and the interpreter has no way to know what belongs to what — which is exactly the point.
Why Python chose this design
This wasn't an accident or a shortcut — it was a deliberate design decision by Python's creator, Guido van Rossum, aimed squarely at readability. Python's guiding philosophy, "The Zen of Python" (try running import this in a Python shell), includes the line "Readability counts." By making indentation mandatory rather than optional, Python forces every piece of code — yours, a coworker's, code from a tutorial you found ten years ago — to look visually consistent by construction. You can't hide a messy, inconsistently-indented block behind a pair of braces on one line, because there are no braces to hide behind.
The practical benefit is that Python code tends to look the way it behaves. In brace languages, misleading indentation (code that's indented as if it's inside a block, but the braces say otherwise) is a genuine, well-documented source of bugs — famously the root cause of Apple's "goto fail" SSL bug. Python sidesteps that entire bug class: if the indentation looks right, it is right, because indentation is the mechanism, not just the appearance.
Aspect | Brace-based languages (C, Java, JS) | Python |
|---|---|---|
Block delimiters | Curly braces | Indentation level |
Indentation enforced? | No — purely cosmetic | Yes — it is the syntax |
Misleading indentation possible? | Yes (braces can disagree with indentation) | No (indentation cannot disagree with itself) |
Empty block |
|
|
The 4-space rule (PEP 8)
Python doesn't mandate an exact number of spaces at the language level — technically any consistent amount works. But the community style guide, PEP 8, standardizes on 4 spaces per indentation level, and virtually every code base, linter, and formatter (including black) enforces it. Sticking to 4 spaces means your code will look the same in any editor, on any team, in any tutorial — which is the entire point of a shared convention.
class BankAccount:
def __init__(self, balance=0):
self.balance = balance
def deposit(self, amount):
if amount > 0:
self.balance += amount
return self.balanceUse 4 spaces per indentation level — never a single space, never 2, never 8.
Each nested block (a body inside an
if,for,def,class, etc.) adds one more 4-space level.Configure your editor to insert spaces (not a tab character) whenever you press the Tab key.
What happens when indentation is wrong: IndentationError
Because indentation carries real meaning, getting it wrong isn't a style nitpick — it's a syntax error the interpreter refuses to run past. The most common case is inconsistent indentation within the same block: two lines that are supposed to be siblings (same block) but are indented by different amounts.
def check_temperature(temp):
if temp > 30:
print("It's hot outside")
print("Stay hydrated")
else:
print("Comfortable weather")Look closely at the third line: print("Stay hydrated") is indented with 7 spaces while the line above it uses 8. They are meant to be two statements in the same if block, but their indentation disagrees. Running this file produces an immediate error — the program never even starts executing:
File "temperature.py", line 4
print("Stay hydrated")
^
IndentationError: unindent does not match any outer indentation levelPython is telling you, quite literally, that it tried to match line 4's indentation to some enclosing block it already knows about, and couldn't. The fix is simply to make every statement in the same block share the exact same indentation:
def check_temperature(temp):
if temp > 30:
print("It's hot outside")
print("Stay hydrated")
else:
print("Comfortable weather")It's hot outside Stay hydrated
Tabs vs. spaces: a classic trap
Tab characters and space characters can look identical in most editors — that's exactly what makes mixing them dangerous. A block that looks perfectly aligned on your screen might actually contain a mix of tabs and spaces that a different editor (or a different tab-width setting) renders completely differently. Python 3 defends against this by disallowing indentation that mixes tabs and spaces in a way it considers ambiguous, and raises a TabError rather than guessing what you meant.
def show_total(items):
total = 0
for item in items:
total += item
return total File "totals.py", line 4
total += item
^
TabError: inconsistent use of tabs and spaces in indentationIn that example, the for loop's body was typed with a literal tab character while every surrounding line uses spaces. It may well have looked "aligned" in the editor that wrote it, but Python refuses to guess whether that tab means "4 spaces," "8 spaces," or something else — so it fails loudly instead of silently misinterpreting your block structure.
Line continuation: splitting statements across lines
Since indentation is meaningful, Python needs an unambiguous way to let a single logical statement span multiple physical lines without that being mistaken for a new block. There are two mechanisms: implicit continuation inside brackets, and explicit continuation with a backslash.
Implicit continuation happens automatically whenever an expression is inside parentheses (), square brackets [], or curly braces {}. Python knows the statement isn't finished until the brackets are balanced, so you can freely break lines — and indent for readability — without any special punctuation. This is the preferred style because it's robust: it can't be broken by an invisible trailing character.
total = (
price_of_apples
+ price_of_bananas
+ price_of_oranges
)
shopping_list = [
"milk",
"eggs",
"bread",
]
result = some_function(
first_argument,
second_argument,
keyword_argument=42,
)Explicit continuation uses a trailing backslash (\) at the very end of a line to tell Python "this statement keeps going on the next line." It works outside of brackets, but it's fragile: the backslash must be the absolute last character on the line — even one trailing space after it silently breaks the continuation (or causes a syntax error) — and it's easy to overlook when skimming code. Most style guides, including PEP 8, recommend preferring implicit (bracket) continuation whenever possible and reserving the backslash for the rare case where brackets aren't natural, such as chaining a long boolean expression.
is_valid = first_condition \
and second_condition \
and third_conditionContinuation style | Syntax | Robustness |
|---|---|---|
Implicit (inside brackets) | Line break anywhere inside | Preferred — no invisible characters to get wrong |
Explicit (backslash) | Trailing | Fragile — a stray trailing space breaks it |
Semicolons: allowed, but discouraged
Unlike C, Java, or JavaScript, Python does not require a semicolon to end a statement — the end of a line is enough. Semicolons are still legal in Python, but their only real use is to place multiple statements on a single physical line, separating each one:
x = 1; y = 2; z = x + y print(z)
3
This works, but it goes against Python's own style conventions. PEP 8 explicitly discourages putting multiple statements on one line with semicolons, because it undercuts the same readability goal that motivated significant indentation in the first place — a reviewer scanning down the left edge of the file for structure will miss a statement hiding after a semicolon. The idiomatic version simply puts each statement on its own line:
x = 1 y = 2 z = x + y print(z)