Skip to main content

Compound statements

Compound statements span multiple logical lines and contain other statements. Each has a header line ending in : and one or more clauses, each with its own header and indented suite.

Source-of-record: CPython compound statements, Python/compile.c, Python/bytecodes.c.

if

if test:
suite
elif test:
suite
else:
suite

Evaluates each test in order; the first truthy one's suite runs. The else clause runs if no test was truthy.

Bytecode: POP_JUMP_IF_FALSE chains with JUMP_FORWARD at the end of each suite.

while

while test:
suite
else:
suite
Step
Evaluate test. If falsy, skip to the else clause (if any).
Run the suite.
break exits without running else.
continue jumps back to the test.

for

for target in iterable:
suite
else:
suite
Step
Get iterator: iter(iterable).
Each iteration: next(it); assign to target; run suite.
StopIteration ends the loop; else runs.
break exits without running else.
continue jumps to the next iteration.

Bytecode: GET_ITER once, FOR_ITER per iteration, END_FOR on normal exhaustion. PEP 669 produces JUMP_BACKWARD after the suite.

try

Forms

try:
suite
except ExcType:
suite
except (T1, T2) as e:
suite
except:
suite # bare except
else:
suite # runs if no exception
finally:
suite # always runs

Semantics

Step
Run the try suite.
If an exception is raised, scan except clauses in order; the first matching type's suite runs.
If no except matches, propagate.
If no exception, run the else suite (if any).
Run the finally suite unconditionally; its bindings are not new exceptions unless they raise.

Inside a handler, the active exception is sys.exc_info(). The as binding is deleted at the end of the handler (SyntaxError in 3.11+ if you assign to it after).

except* (PEP 654)

try:
suite
except* ExcType:
suite

The exception is expected to be an ExceptionGroup. except* clauses filter and split the group; multiple except* handlers may run for one group. Exceptions not matched re-raise in a residual group.

You cannot mix except and except* in the same try.

with

with manager:
suite

with manager as name:
suite

with manager1 as n1, manager2 as n2:
suite

with (
manager1 as n1,
manager2 as n2,
):
suite
Step
Evaluate manager. Call manager.__enter__(). Bind name.
Run suite.
On normal exit: manager.__exit__(None, None, None).
On exception: manager.__exit__(type, value, tb). If it returns truthy, the exception is suppressed.

Parenthesised multi-item with (PEP 617) allows trailing commas and multi-line layout.

match (PEP 634)

match subject:
case pattern_a:
suite
case pattern_b if guard:
suite
case _:
suite

The subject is evaluated once. Each case's pattern is tested in order; the first that matches (and whose guard passes) runs. Patterns bind names as described in Grammar -> Patterns.

PatternMatches
x (capture)Anything; binds x.
_Anything; no binding.
1, "s"Literal equality.
True/False/NoneSingletons; identity match.
[a, b, c]Sequence of length 3.
[a, *rest]Sequence of length >= 1.
{1: x}Mapping with key 1; binds value to x.
Point(x, y=0)Class pattern using __match_args__.
pat1 | pat2OR.
pat as nameMatch pat and bind to name.
dotted.nameValue pattern (constant lookup).

Function definition

@decorator1
@decorator2(arg)
def name[T1, T2](params) -> return_annotation:
suite
ElementEffect
@decoratorApply: name = decorator(name). Stacks bottom-up.
[T1, T2]PEP 695 type parameters; creates TypeVars.
ParametersSee below.
-> annotationReturn annotation (lazy in 3.14).
BodyCode object built and bound to name in current scope.

Parameter syntax

def f(
pos_only_a, pos_only_b, /,
pos_or_kw, *args,
kw_only,
**kwargs,
):
FormKind
namePositional-or-keyword.
name=defaultSame, with default.
*argsVariadic positional.
* (alone)Marks subsequent parameters as keyword-only.
name, after * or *argsKeyword-only.
/ (alone)Marks all previous parameters as positional-only.
**kwargsVariadic keyword.

Generators, coroutines, async generators

Function formBody containsResult of call
def f(...)normal codeReturn value.
def f(...)yield / yield fromGenerator object.
async def f(...)await / normal codeCoroutine object.
async def f(...)yieldAsync generator object.

Class definition

@decorator
class Name[T](base1, base2, metaclass=Meta, **kwds):
suite
Step
Evaluate decorators (deferred to after class creation).
Resolve type parameters (PEP 695).
Evaluate bases and keyword arguments.
Pick a metaclass (explicit or most-derived).
Call metaclass.__prepare__(name, bases, **kwds) if defined; get namespace mapping.
Execute the class body in the namespace.
Call metaclass(name, bases, namespace, **kwds).
Apply decorators in reverse order.
Bind the result to Name.

Body execution

A class body sees the enclosing module/function scope for reads, but bindings inside the class body bind into the namespace mapping (eventually the class's __dict__). Methods inside cannot see class bodies as part of their scope chain.

async def

async def f(...):
suite

async with manager as name:
suite

async for target in async_iterable:
suite

Inside an async def:

StatementEffect
await exprSuspend until expr resolves; resume with its result.
async forIterate over an async iterable.
async withContext manager with __aenter__ / __aexit__.
yieldMakes the function an async generator.
return valueEnds the coroutine; value becomes the awaiter's result.

await outside an async def is a SyntaxError. async for and async with are also restricted to async contexts, with one exception: top-level await is allowed in compile(..., mode='eval') with PyCF_ALLOW_TOP_LEVEL_AWAIT.

Suite layout

header:
statement
statement

header: statement; statement

header:
statement1
statement2
header:
statement3

A suite can be one of:

FormNotes
Simple statement on the same line as headerif x: pass.
Multiple simple statements on the same lineif x: pass; print(1).
NEWLINE + INDENT blockStandard form.

Decorator order

@a and @b on the same definition compose as b(a(...)) would in Python:

@a
@b
def f(): ...
# equivalent to: f = a(b(f))

Decorator expressions can be any valid expression in 3.9+. They are evaluated before the decorated definition runs, but applied after.

Gopy status

AreaState
if/elif/elseComplete.
while/for with elseComplete.
try/except/else/finallyComplete.
except* and exception groupsComplete.
with (parenthesised, multi-item)Complete.
match/caseComplete.
def/async def/decoratorsComplete.
class/__prepare__/metaclassesComplete.
PEP 695 type paramsComplete.

Reference