Control Flow
Making decisions with if, elif and else, conditional expressions, and structural pattern matching with match.
Conditions
A program that always does the same thing is of limited use. Real programs decide: charge shipping only below a certain order total, warn only when the disk is almost full. The order in which statements run is called the program's control flow, and the simplest way to change it is to run some code only when something is true.
That "something" is a
condition: an expression that
Python evaluates to decide which way to go. Usually it is a
comparison, which produces True or False:
temperature = 23
print(temperature > 20)
print(temperature == 30)
print(type(temperature > 20))
True False <class 'bool'>
You can combine comparisons with and,
or and not, and chain them, as in
0 <= percent <= 100. The page on
operators and expressions
covers all of these in detail. As you will see
below, a condition does not even
have to be a bool: any value will do.
The if statement
An if statement consists of the keyword
if, a condition, a colon, and an indented block. When
the condition is true, Python runs the block; when it is false,
Python skips it and continues after it.
temperature = 31
if temperature > 30:
print("It's hot today.")
print("Drink plenty of water.")
print("Have a nice day.")
It's hot today. Drink plenty of water. Have a nice day.
With temperature = 25, only the last line would be
printed: it is not indented, so it is not part of the
if.
Blocks and indentation
A block is a group of statements that belong together and run as a unit. In Python, a block starts after a line that ends in a colon, and consists of the lines below it that are indented further — four spaces by convention. The block ends at the first line that is indented less again. Every line in one block must have exactly the same indentation.
A block can never be empty. If you leave it out, Python refuses to run the program at all:
stock = 0
if stock == 0:
print("Sold out")
IndentationError: expected an indented block after 'if' statement on line 2
See indentation for the general rules, and the pass statement below for how to write a block that does nothing.
else
An else clause gives the alternative: its block runs
when the condition is false. It has no condition of its own, and it
is written at the same indentation as its if. Exactly
one of the two blocks runs.
age = 16
if age >= 18:
print("You may vote.")
else:
print("You may not vote yet.")
You may not vote yet.
elif
For more than two possibilities, add one or more
elif clauses (short for "else if"). Python tests the
conditions from top to bottom and runs the block of the
first one that is true. It then skips the rest of
the chain, even if later conditions are also true. The optional
else at the end catches every case that no condition
matched.
score = 74
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
print("Grade:", grade)
Grade: C
x = 10
if x > 5:
print("more than 5")
if x > 8:
print("more than 8")
else:
print("8 or less")
more than 5 more than 8
Nested if statements
A block can contain any statements, including another
if. This is called nesting. The inner
if is only reached when the outer condition is true,
and each level is indented one step further.
has_ticket = True
age = 15
if has_ticket:
if age >= 16:
print("Enjoy the film.")
else:
print("You need an adult with you.")
else:
print("Please buy a ticket first.")
You need an adult with you.
Indentation decides which if an
else belongs to: the inner else lines up
with the inner if, the outer one with the outer
if. Deep nesting quickly becomes hard to read. Often
you can flatten it by combining conditions with and, or
by using elif:
has_ticket = True
age = 15
if not has_ticket:
print("Please buy a ticket first.")
elif age >= 16:
print("Enjoy the film.")
else:
print("You need an adult with you.")
You need an adult with you.
Truthy and falsy values
A condition does not have to be True or
False. Python accepts any value and asks it whether it
counts as true. This is called
truthiness: a value that
counts as true is truthy, a value that counts as false is
falsy. The built-in function bool() shows the
answer Python uses.
The rule is short: these values are falsy —
FalseandNone;-
zero of every numeric type:
0,0.0,0j(and alsoDecimal(0)andFraction(0, 1)); -
every empty collection:
"",[],(),{},set()andrange(0); -
objects of your own classes that say so, through a
__bool__()method that returnsFalseor a__len__()method that returns0.
Everything else is truthy.
values = [0, 0.0, "", [], {}, None, False, 42, -1, "0", " ", [0], "False"]
for value in values:
print(repr(value), "->", bool(value))
0 -> False
0.0 -> False
'' -> False
[] -> False
{} -> False
None -> False
False -> False
42 -> True
-1 -> True
'0' -> True
' ' -> True
[0] -> True
'False' -> True
Truthiness makes short, readable checks possible: "if there is a name", "if the list has items".
name = ""
basket = ["bread", "milk"]
if name:
print("Hello,", name)
else:
print("Name is missing.")
if basket:
print("Items in basket:", len(basket))
Name is missing. Items in basket: 2
The conditional expression
Sometimes an if/else only chooses between
two values. For that, Python has the
conditional expression
(other languages call it the ternary operator):
value_if_true if condition else value_if_false
Python first evaluates the condition, then evaluates and returns
only the value on the chosen side. Because it is an
expression, not a statement, you can use it anywhere a value is
expected: on the right of =, as an argument, inside an
f-string.
stock = 0
status = "in stock" if stock > 0 else "sold out"
print(status)
temperature = 12
print("Wear a coat." if temperature < 15 else "A T-shirt is fine.")
items = 1
print(f"{items} {'item' if items == 1 else 'items'} in your cart")
sold out Wear a coat. 1 item in your cart
The else part is required: x if c on its
own is a SyntaxError. Keep conditional expressions
short. If you are tempted to nest them, write a normal
if statement instead.
The pass statement
The
pass statement
does nothing at all. It exists because Python's syntax requires at
least one statement in every block. Use it as a placeholder while
you are still writing the code, or to state explicitly that a case
needs no action:
order_total = 80
if order_total >= 100:
pass # TODO: add the free gift
else:
print("Add", 100 - order_total, "to get a free gift.")
Add 20 to get a free gift.
pass works in every kind of block: loops, functions and
classes as well. A comment alone is not enough, because Python
ignores comments — a block containing only a comment is still empty.
Pattern matching with match
The
match statement,
added in Python 3.10, compares one value — the subject —
against a series of patterns. Each pattern sits in a
case clause. Python tries the cases from top to bottom
and runs the block of the first one that matches; the others are
skipped. If no case matches, nothing happens.
It resembles the switch statement of other languages,
but there is no fall-through (no break is needed) and
the patterns can do much more than compare with a constant.
match and case are soft keywords:
they only have a special meaning in this statement, so they can
still be used as ordinary names elsewhere.
Literal patterns and alternatives
The simplest pattern is a literal, such as a number or a string: it
matches when the subject is equal to it. The | symbol
joins alternatives ("this or that"), and the
wildcard _ matches anything, so
case _: at the end plays the role of else.
for status in [200, 302, 404, 500]:
match status:
case 200:
print(status, "OK")
case 301 | 302:
print(status, "Redirect")
case 404:
print(status, "Not found")
case _:
print(status, "Other status")
200 OK 302 Redirect 404 Not found 500 Other status
Capture patterns and the wildcard
A bare name in a pattern is a capture pattern. It does not
compare anything: it matches every value and binds it to that name,
so the block can use it. The wildcard _ also matches
everything, but binds nothing.
Because a bare capture pattern always matches, it may only appear in
the last case. Anywhere else, the cases after it could
never be reached, and Python reports a SyntaxError.
Sequence patterns
A pattern in square brackets (or parentheses) matches a list or
tuple with the same number of items, where each item matches its own
sub-pattern. Literals inside must be equal, names capture the item
in that position, and *name captures all remaining
items as a list. This makes match a natural fit for
simple commands:
commands = [["quit"], ["go", "north"], ["drop", "lamp", "key"], ["dance"]]
for command in commands:
match command:
case ["quit"]:
print("Goodbye")
case ["go", direction]:
print("Going", direction)
case ["drop", *items]:
print("Dropping", items)
case _:
print("Unknown command:", command)
Goodbye Going north Dropping ['lamp', 'key'] Unknown command: ['dance']
Guards
A guard is an if condition after a pattern:
case pattern if condition:. The case only matches when
the pattern matches and the condition is true. Guards often
go together with a capture pattern, to test the captured value.
for temperature in [-5, 0, 18, 35]:
match temperature:
case 0:
print(temperature, "freezing point")
case t if t < 0:
print(t, "below freezing")
case t if t >= 30:
print(t, "hot")
case t:
print(t, "mild")
-5 below freezing 0 freezing point 18 mild 35 hot
Patterns can also match dictionaries, objects of a class, and
combinations of all of these. For everyday decisions on a single
number or string, though, if/elif is often
just as clear; match shines when you need to check the
shape of a value and take it apart at the same time.