# Outside any section
if True:
...
# Inside a section
# See? It's indented!
# Outside any sectionMore Control Flow Tools (Part I)
Today, we’re discussing sections 4.1-4.7 of The Python Tutorial. These are
- 4.1
ifStatements - 4.2
forStatements - 4.3 The
range()Function - 4.4
breakandcontinueStatements - 4.5
elseClauses on Loops - 4.6
passStatements - 4.7
matchStatements
Next month, we’ll cover 4.8-4.9: Functions
Intro
The goal of this section is to control how we run certain sections of code.
In Python, you create a section of code by indenting it:
4.1 if Statements
Conditionals: for running (indented) code only under certain conditions
if: always necessaryelif: optional, additional conditions (only if the previous fail)else: optional, catches anything that fails
# Conditions look like
print(1 == 1)
print(1 != 1)True
False
# Just a single if
i_feel = "happy"
if i_feel == "happy":
print("I feel happy")
print("Still indented")
print("This always runs")I feel happy
Still indented
This always runs
# if-elif-else
i_feel = "confused"
if i_feel == "happy":
print("I feel happy")
elif i_feel == "unhappy":
print("I feel unhappy")
else:
print("I don't feel happy or unhappy")I don't feel happy or unhappy
# An example with if-elif but no else
i_feel = "confused"
if i_feel == "happy":
print("Happy")
elif i_feel == "sad":
print("Sad")
print("Moving on!")Didn't match.
Moving on!
4.2 for Statements
for statements let you run an indented block multiple times, once for each element in an iterable (something with multiple elements, like a list).
# Measure some strings:
words = ['cat', 'window', 'defenestrate']
for w in words:
print(w, len(w))cat 3
window 6
defenestrate 12
It’s possible to modify the iterable during the list. This can make things unpredictable, don’t do it. If you have to, use a copy of the object.
# Measure some strings:
words = ['cat', 'window', 'defenestrate']
for w in words.copy():
print(w, len(w))
words.append(w)
print(words)cat 3
window 6
defenestrate 12
['cat', 'window', 'defenestrate', 'cat', 'window', 'defenestrate']
# Advanced: looking at how for loops work behind-the-scenes
# This is what a for loop does behind the scenes:
some_iterable = ["a", "b", "c"]
iterator_for_the_loop = iter(some_iterable)
# This happens for all the elements, so really should be a while loop
placeholder = next(iterator_for_the_loop)
print(placeholder)
placeholder = next(iterator_for_the_loop)
print(placeholder)
placeholder = next(iterator_for_the_loop)
print(placeholder)
# next(iterator_for_the_loop)
# To handle the end of the loop
try:
placeholder = next(iterator_for_the_loop)
except StopIteration:
pass
# Equivalent code as for loop
for placeholder in some_iterable:
print(placeholder)a
b
c
a
b
c
4.3 The range() Function
It’s common to loop over a range of numbers. The range() function makes that simpler. It represents a list of integers from start to stop every step:
# default start=0 and step=1
range(stop)
# default step=1
range(start, stop)
# with everything specified
range(start, stop, step)
for i in range(20,-21, 4):
print(i)
my_range = range(10)
sum(my_range)45
range() objects have some weird properties
startis included butstopis excluded- You can use functions like
sum()to add up the range - They don’t store all the numbers at once (makes them very efficient).
4.4 break and continue Statements
Helper statements for loops.
break exits the loop:
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
breakapple
# Useful with a conditional
for fruit in fruits:
print(fruit)
if fruit == "banana":
print("Yuck!")
breakapple
banana
Yuck!
continue skips to the start of the next iteration. These are both useful in conjunction with conditionals:
for fruit in fruits:
if fruit == "banana":
print("yuck!")
continue
print(fruit)apple
yuck!
cherry
4.5 else Clauses on Loops
This is an odd but useful one. 99% of the time else statements are in if blocks and catch anything that fails the conditions.
When else follows a loop, it catches anything that didn’t break out of the loop. If the loop ends without break, the else condition will run.
Let’s see where this is useful:
fruits = ["apple", "pear", "cherry"]
for fruit in fruits:
print(fruit)
if fruit == "banana":
print("Yuck!")
break
else:
print("Didn't hit break - no yucky fruit")apple
pear
cherry
Didn't hit break - no yucky fruit
They also work for while loops. Remember them? They’re like conditionals+loops combined, they run an indented block until a condition is false.
4.6 pass Statements
These are simpler - pass statements do nothing. Nothing at all!
passif "banana" in fruits:
passfor fruit in fruits:
passWhy have them then? Because empty indented blocks throw an error:
if "banana" in fruits:
# do this later
print("Moving on")Cell In[38], line 4 print("Moving on") ^ IndentationError: expected an indented block after 'if' statement on line 1
With pass, we can set up the framework but leave the implementation for later.
if "banana" in fruits:
pass # do this later
elif "apple" in fruits:
pass
else:
pass
print("Moving on")Moving on
4.7 match Statements
These are for pattern matching, and are the most advanced feature we’ll look at today. You don’t need to use these - an if stack can always do the job. But it’s useful and can be quick.
You match something to a case (usually multiple):
match something:
case possibility_1:
# some code
case possibility_2:
# some code
A ‘possibility’ of _ will match anything (it’s a wildcard). Cases are checked in order and only one is matched.
status = 500
match status:
case 400:
print("Bad request")
case 404:
print("Not found")
case 418:
print("I'm a teapot")
case _:
print("Something's wrong with the internet")Something's wrong with the internet
Combine several options with vertical bar | (“or”)
status = 401
match status:
case 400:
print("Bad request")
case 401 | 403 | 404:
print("Not allowed")
case 404:
print("Not found")
case 418:
print("I'm a teapot")
case _:
print("Something's wrong with the internet")Not allowed
So far so good. It gets weird though. You can implicitly assign to variables if you put them in the patterns!
point = (3, 4)
match point:
case (x, y):
print(x,y)
print(x * y)3 4
12
This magically created the variables x and y and assigned their values!
A more complex example is given in The Python Tutorial
point = (3, 4)
match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
print("Not a point!")X=3, Y=4
Lastly: guards. Let’s say the pattern matches but you still want to exclude specific cases. Use if to do this:
point = (4, 4)
match point:
case (x,y) if x == y:
print(f"Y=X at {x}")
case (x, y):
print(f"Not on the diagonal")Y=X at 4