Python - Control Flow
If / Else
You can conditionally run a line of code like this:
if x == 5:
print('equal to five')
Conditionally run a statement and run a different statement if the condition is not true:
if x == 5:
print('equal to five')
else:
print('not equal to five')
If one condition is true execute a statement, otherwise check another condition:
if x < 5:
print('less than 5')
elif x == 50:
print('Medium')
A more complete example:
if x < 5:
print('less than 5')
x = x + 2
elif x == 50:
print('Medium')
elif x == 100:
print('Large')
else:
print('Default')
Loops
Loops are terrific. They allow you to repeat a task over and over in an iterative manner.
Range - Quick Background
We’re going to breifly cover ranges because they are important and loops will be easier to understand when you’ve covered these. The range() function creates an iterator ( more on these in a later section ). This can’t be printed directly but can be looped over.
- Printing a range doesn’t print the series since it is an iterable.
Create a range of numbers 0 to 9 ( size 10 ):
range(10)
# 0 1 2 3 4 5 6 7 8 9
Range 5 to 14:
range(5, 15)
# 5 6 7 8 9 10 11 12 13 14
Range 5 to 24, step by 2:
range(5, 25, 2)
# 5 7 9 11 13 15 17 19 21 23
sum(range(4))
For Loops
Here is an example of a very basic, standard for loop. It loops over a list and prints each element.
a = ["pizza", "noodle", "burger"]
for i in a:
print(i)
Loop over a range and print the numbers:
for i in range(5):
print(i)
Iterate over indices showing the index and value:
a = ["pizza", "noodle", "burger"]
for i in range(len(a)):
print(i, a[i])
Python C style for loop - you can just use a range for this:
for i in range(0, 9, 2):
print(i)
While Loops
While loops can be useful but in most cases you will want to stick with for loops.
Generic while loop:
x = 0
while x < 50:
print("x: " + str(x))
x = x + 1
While loops are great for creating infinite loops:
while True:
print("x")
Looping Over Collections - Tip
Modifying a list or other collection while looping over it can be tricky and has the potential to create issues. Here are a couple over other ways to do this.
Create a copy and loop over that:
a = {'Breakfast': 'pizza', 'Lunch': 'noodle', 'Dinner': 'burger'}
for meal, item in a.copy().items():
if item != 'pizza':
del a[meal]
Just create a new dictionary:
a = {'Breakfast': 'pizza', 'Lunch': 'noodle', 'Dinner': 'burger'}
b = {}
for meal, item in a.items():
if item == 'pizza':
b[meal] = item
Break, Continue, Else
- continue - start next iteration of loop
- break - stop executing loop
- else - executes at the end when no break occurs
Break the loop early when we find “taco”:
a = ["pizza", "noodle", "taco", "burger", "sushi"]
for i in a:
if i == "taco":
break
Print out a message if the loop terminates without a match ( no break ):
a = ["pizza", "noodle", "taco", "burger", "sushi"]
for i in a:
if i == "taco":
break
else:
print("no tacos found")
Skip to the next iteration of the loop if we’ve found “taco”. Basically don’t bother checking food if we already have “taco”.
a = ["pizza", "noodle", "taco", "burger", "sushi"]
for i in a:
if i == "taco":
continue
print("checking food...")
if i == "pizza":
print("found pizza")
Pass - Place Holder
- pass - does nothing, like a place holder that keeps syntax valid
Infinite loop, wait for keyboard interrupt:
while True:
pass
Create a class for future use but don’t define it yet:
class SomeClass:
pass
Define a fuction but don’t create an implementation yet. This way we can write all of the code that uses this function first.
def function1(a, b, c):
pass
Match Statements
Match:
- like switch statement from other langs
- only first matched pattern executes
- can extract components
Multiple options:
match option:
case 123:
print("First Option")
case 456:
print("Second Option")
case 1000:
print("Another Option")
case _:
print("Default - Something is wrong")
Using multiple literals as single pattern:
match option:
case 123 | 789 | 12:
print("found a match")
Using multiple literals as single pattern:
Can also match both numbers and strings:
match option:
case "abc" | 789 | 12:
print("found a match")
Here is an example where do the following:
- unpack patterns ( also binds variables ):
- unpack variables combined with literals
some_tuple = (5, 8)
match some_tuple:
case (0, 0):
print("Start")
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("default")
Weird example doing this with a class:
class SomeClass:
def __init__(self, x, y):
self.x = x
self.y = y
sc = SomeClass(5, 8)
match sc:
case SomeClass(x=0, y=0):
print("Start")
case SomeClass(x=x, y=0):
print(f"X={x}")
case SomeClass(x=0, y=y):
print(f"Y={y}")
case SomeClass(x=x, y=y):
print(f"X={x} Y={y}")
case _:
print("default")
Use an if statement ( called a guard ). This allows you to apply additional checks to each case.
some_tuple = (5, 5)
match some_tuple:
case (x, y) if x == y:
print(f"X={x}, Y={y}")
case _:
print("default")
Capture a subpattern with the “as” keyword:
some_tuple = ((5, 5),(1,2))
match some_tuple:
case ((x, y), (a, b) as i2):
print(f"Sub:{i2}")
case _:
print("default")
More Conditions
The operator “in” can be used to test membership in a collection. The operator “is” can be used to test if objects are actually the same object ( not just that their values are the same ). The operator “not” can be used for negation.
in # test if item is in a collection
not in
is # test if same object
is not
Check multiple conditions:
You can terst multiple conditions in on expression like this:
a < b == c
- And/or/not have lower priority than comparison operators.
Priorities between and/or/not:
and | |
or | lowest priority |
not | highest priority |
These are aquivalent:
A and not B or C
(A and (not B)) or C
Short-circuit operators:
- These stop evaluating when the outcome is known
- Return value is the last evaluated arg
Assign results of comparison:
non_null = str1 or str2 or str3
:= walrus operator, use to assign inside an expression
Comparing Sequences
Same type sequences can be compared.
- Elements are compared one at a time. When a different element is found it is compared lexographically.
- If one sequence is a subset, it will be smaller )
- Strings are compared by the Unicode code point number.
- Objects of different types need to have a comparison method.
Example of comparrisions from official Python tutorial:
(1, 2, 3) < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)