if / elif / else
def classify(n):
if n < 0:
return "negative"
elif n == 0:
return "zero"
else:
return "positive"
for x in [-3, 0, 7]:
print(classify(x))negative
zero
positivewhile
n, total = 5, 0
while n > 0:
total += n
n -= 1
print(total)15while … else
The else runs if the loop completes without break.
x = 0
while x < 3:
x += 1
else:
print("loop finished cleanly")loop finished cleanlyfor
Iterates anything that produces a sequence: list, tuple, dict, set, range, string, generator.
for ch in "abc":
print(ch)a
b
c# Tuple unpacking in the loop variable
pairs = [("a", 1), ("b", 2), ("c", 3)]
for key, value in pairs:
print(key, value)a 1
b 2
c 3# Star pattern works too
for first, *rest in [[1, 2, 3], [4, 5, 6, 7]]:
print(first, rest)1 [2, 3]
4 [5, 6, 7]break and continue
for i in range(10):
if i == 5:
break
if i % 2 == 0:
continue
print(i)1
3for … else
Runs when the loop exhausts its iterator (no break).
for i in range(3):
pass
else:
print("done")donematch / case
Subset supported: literal patterns, capture variables, _ wildcard, OR (|), guards (if), sequence patterns with *rest.
Sequence-pattern items must be literals (int / float / str / True / False / None), capture names, or _. Nested sequences (case [[a, b], c]:), mapping patterns ({"key": x}), class patterns (Point(x=0)), and as captures are unsupported, use chained if / elif.
def classify(p):
match p:
case 0:
return 'zero'
case 1 | 2 | 3:
return 'small'
case n if n < 0:
return 'negative'
case [x, y] if x == y:
return 'diagonal'
case [first, *middle, last]:
return f'span {first}..{last}'
case _:
return 'other'
print(classify(0))
print(classify(2))
print(classify(-7))
print(classify([3, 3]))
print(classify([1, 2, 3, 4, 5]))zero
small
negative
diagonal
span 1..5def describe(n):
match n:
case 0:
return "zero"
case 1:
return "one"
case _:
return "many"
for x in [0, 1, 2, 99]:
print(describe(x))zero
one
many
manytry / except / else / finally
def safe_div(a, b):
try:
return a / b
except ZeroDivisionError:
return None
print(safe_div(10, 2))
print(safe_div(10, 0))5.0
None# Multiple handlers and finally
try:
x = int("abc")
except ValueError:
x = -1
finally:
print("cleanup")
print(x)cleanup
-1# Bare except catches everything
try:
raise "boom"
except:
print("caught")caughtraise
def positive(n):
if n < 0:
raise ValueError
return n
try:
positive(-1)
except ValueError:
print("rejected")rejectedraise X from Y raises X. The from clause parses and the cause evaluates, but __cause__ / __context__ aren’t preserved, only X reaches the handler.
try:
raise ValueError from KeyError
except ValueError:
print("caught the ValueError")caught the ValueErrorHandlers match on class and declared parents. except Exception catches ValueError, RuntimeError, KeyError, etc:
try:
raise RuntimeError("boom")
except Exception:
print("subclass caught")subclass caughtException names available
Pre-bound exception classes (with their parent links so except <Parent>: matches subclasses) are listed in Limits and errors, Runtime.
with
with drives the context-manager protocol: evaluate the expression, call __enter__, bind the result to as. On exit, __exit__(exc_type, exc_value, traceback) runs, (None, None, None) on normal completion, live exception info on raise. Truthy return suppresses; falsy propagates. See /language/dunders.
x = [1, 2]
with x as items:
print(len(items))
print("after")2
afterMultiple targets:
a, b = "first", "second"
with a as x, b as y:
print(x, y)first secondassert
def reciprocal(n):
assert n != 0, "n must be non-zero"
return 1 / n
print(reciprocal(4))0.25A failed assertion raises AssertionError; catchable with except AssertionError, except Exception, or bare except. The optional message after the comma is evaluated only when the assertion fails and becomes the exception’s argument (e.args).
del
Removes a binding from the slot. Works on plain names and indexed positions.
x = 42
del x
try:
print(x)
except NameError:
print("gone")gone