6 Code Blocks: Conditional and Looping Statements
6.1Lesson goals¶
Understand and navigate through code blocks.
Construct conditional statements using the
ifkeyword.Iterate code using the
forandwhilekeywords.Utilize list comprehension to quickly create and modify lists.
6.2Overview¶
Everything we have written so far follows a linear process: the Python interpreter run each line of code sequentially until it reaches the end. There are times in which we want our code to branch out into various paths depending on a set of inputs and requirements. This lesson will cover how we can use conditional checks to allow code to run under certain requirements and how we can iterate / loop a section of code multiple times.
6.3Code blocks¶
A code block is a section of code that runs from top to bottom in sequential order until it either ends or is redirected to another code block. Below is a simple example of code block:
a = 5 # Start code block
print(f"a is {a}")
equal_five = (a == 5)
print(f"a equals 5?: {equal_five}") # End code blocka is 5
a equals 5?: True
Seems straightforward! But what if we want to run one section of code if a condition is met, like when a == 5, and a
different section of code if the condition is not met, like a != 5? That type of branching logic will mean not all
the code will run, instead only certain blocks of code will run depending on the conditional. Conditional and looping
statements allow us to this!
6.4Conditional statements¶
A conditional statement is a command that redirects program flow if a
certain testing condition is met. This is often done using boolean logic with bool objects.
6.4.1The if keyword¶
The if keyword is used to create a conditional
statement where, if the statement is True, then it will proceed to the code block that follows. The code block below
uses the if keyword to output and additional line of text if a >= 5:
a = 5 # Start code block 1
print(f"a is {a} (Code Block 1)") # 1
# 1
if a >= 5: # Start code block 2
print("a >= 5 (Code Block 2)") # 2
a = a * 10 # End code block 2
# 1
print(f"a is {a} (Code Block 1)") # End code block 1a is 5 (Code Block 1)
a >= 5 (Code Block 2)
a is 50 (Code Block 1)
Code block 2 only runs if a >= 5 is True. Notice how this is much easier to read than the previous one line
check from earlier. Let’s change the value of a to be less than or equal to 5 and see what happens!
a = 3 # Start code block 1
print(f"a is {a} (Code Block 1)") # 1
# 1
if a >= 5: # Start code block 2
print("a >= 5 (Code Block 2)") # 2
a = a * 10 # End code block 2
# 1
print(f"a is {a} (Code Block 1)") # End code block 1a is 3 (Code Block 1)
a is 3 (Code Block 1)
Code Block 2 is skipped! We have redirected program flow!
6.4.2Structure of the if statement¶
There are a few key formatting aspects the above if statement to be aware of. The command if a >= 5: that starts the second code block is called in Python a compound statement. This statement begins with the if
keyword and ends with the colon character :.
The following two lines after the if statement are part of the new code block (code block 2) which is designated by
the indented lines of code. This indent
represents four SPACEBAR keystrokes, which is the
standard length for each indentation level. A
TAB keystroke also works if your IDE sets this to four spaces. When we want to complete the code block, we simply un-indent to match the previous code block and continue writing code.
6.4.3Indentations matter!¶
It is crucial that you are consistent with the indentation in a code block, or else you will get errors. Below is an example of a code block without proper indentation:
a = 5 # Start code block 1
print(f"a is {a} (Code Block 1)") # 1
# 1
if a >= 5: # Start code block 2
print("a >= 5 (Code Block 2)") # 2
a = a * 10 # End code block 2
# 1
print(f"a is {a} (Code Block 1)") # End code block 1 Cell In[4], line 5
print("a >= 5 (Code Block 2)") # 2
^
IndentationError: expected an indented block after 'if' statement on line 4
The error message IndentationError: expected an indented block after 'if' statement on line 4 means that
we forgot to indent the code block after the if statement. Too much indenting is also a problem, as highlighted
in the code below:
a = 5 # Start code block 1
print(f"a is {a} (Code Block 1)") # 1
# 1
if a >= 5: # Start code block 2
print("a >= 5 (Code Block 2)") # 2
a = a * 10 # End code block 2
# 1
print(f"a is {a} (Code Block 1)") # End code block 1 Cell In[5], line 6
a = a * 10 # End code block 2
^
IndentationError: unexpected indent
The error message IndentationError: unexpected indent points to the fact that we have not uniformly indented the code
block. There are four extra spaces in the a = a * 10 line. Indentation needs to be consistent throughout the code
block. Improper spacing and indenting will generate errors. Indentation overall significantly improves overall
readability, but it requires you to be mindful of your formatting!
6.4.4The else clause¶
The else clause allows us to do
something with the False outcome of the if statement. Using our
initial if statement code block as an example, let’s add an else clause that prints
out that a is less than 5:
a = 3 # Start code block 1
print(f"a is {a} (Code Block 1)") # 1
# 1
if a >= 5: # Start code block 2
print("a >= 5 (Code Block 2)") # 2
a = a * 10 # End code block 2
else: # Start of code block 3
print("Hey! a < 5! (Code Block 3)") # End of code block 3
# 1
print(f"a is {a} (Code Block 1)") # End code block 1a is 3 (Code Block 1)
Hey! a < 5! (Code Block 3)
a is 3 (Code Block 1)
Here, the else clause catches all cases when the if condition is False. The flow of the program does not enter
into code block 2, but is instead directed towards code block 3, which reassigns a to be itself divided by 10.
6.4.5The elif keyword¶
The elif keyword (pronounced: “else if”) allows us to chain multiple if statements together. So if the first if
statement flags a False condition, we can then check another conditional. The code block below demonstrates this:
a = 3 # Start code block 1
print(f"a is {a} (Code Block 1)") # 1
# 1
if a >= 5: # Start code block 2
print("a >= 5 (Code Block 2)") # 2
a = a * 10 # End code block 2
elif a >= 3: # Start code block 3
print("3 =< a < 5 (Code Block 3)") # End code block 3
else: # Start of code block 4
print("Hey! a < 3! (Code Block 4)") # End of code block 4
# 1
print(f"a is {a} (Code Block 1)") # End code block 1a is 3 (Code Block 1)
3 =< a < 5 (Code Block 3)
a is 3 (Code Block 1)
In this example the second code block with the if statement is False and skipped so the interpreter moves to the
elif keyword that evaluates True.
It is important to note when chaining multiple if and elif statements, the first condition that evaluates True
will be the one that is executed. This is highlighted in the example below:
a = 6 # Start code block 1
print(f"a is {a} (Code Block 1)") # 1
# 1
if a >= 5: # Start code block 2
print("a >= 5 (Code Block 2)") # 2
a = a * 10 # End code block 2
elif a >= 3: # Start code block 3
print("3 =< a < 5 (Code Block 3)") # End code block 3
else: # Start of code block 4
print("Hey! a < 3! (Code Block 4)") # End of code block 4
# 1
print(f"a is {a} (Code Block 1)") # End code block 1a is 6 (Code Block 1)
a >= 5 (Code Block 2)
a is 60 (Code Block 1)
In this example a is set to 6 so both the if and the elif conditionals should return True. However, since the if conditional is the first conditional evaluated True, its code block is executed and all other code blocks
associated with the starting if statement (the elif and else conditional statements) are ignored.
6.4.6The and and or Boolean operators¶
A conditional statement can be constructed with any number of conditional clauses chained together using the
and and or Boolean operators. The and operator will
evaluate to True if and only if all clauses evaluate to True. The code below demonstrates how and is used to
chain two conditionals together:
# `and` Boolean operator demonstration
number = 10
# Individual Boolean checks checks
print("Individual Boolean checks")
print("~~~~~~~~~~~~~~~~")
print("number > 8:", number > 8)
print("number < 11:", number < 11)
print("(number > 8) and (number < 11):", (number > 8) and (number < 11))
print("\n")
# Using `and` in an `if` statement
print("Using `and`")
print("~~~~~~~~~~~~~~~~")
if (number > 8) and (number < 11):
print(f"The value {number} is between 8 and 11")
else:
print(f"The value {number} is outside of 8 and 11")Individual Boolean checks
~~~~~~~~~~~~~~~~
number > 8: True
number < 11: True
(number > 8) and (number < 11): True
Using `and`
~~~~~~~~~~~~~~~~
The value 10 is between 8 and 11
The or operator will evaluate to True if one or more clauses evaluate to True. It will evaluate False only if
all clauses are False. The code below demonstrates how or is used to chain two conditionals together:
# `or` Boolean operator demonstration
number = 5
# Individual Boolean checks checks
print("Individual Boolean checks")
print("~~~~~~~~~~~~~~~~")
print("number > 8:", number > 8)
print("number < 11:", number < 11)
print("(number > 8) or (number < 11):", (number > 8) or (number < 11))
print("\n")
# Using `or` in an `if` statement
print("Using `or`")
print("~~~~~~~~~~~~~~~~")
if (number > 8) or (number < 11):
print(f"The value {number} is outside of 8 and 11")
else:
print(f"The value {number} is between of 8 and 11")Individual Boolean checks
~~~~~~~~~~~~~~~~
number > 8: False
number < 11: True
(number > 8) or (number < 11): True
Using `or`
~~~~~~~~~~~~~~~~
The value 5 is outside of 8 and 11
6.4.7Chaining conditionals¶
As noted, you can chain these keywords together to evaluate multiple conditional clauses like in the example below:
if True and False and True and False or True:
print("True? I guess so!")True? I guess so!
When chaining together conditional clauses it is useful to use the parentheses symbols ( and ) to break down the
logic into manageable chunks. Parentheses will help the readability when trying to parse a long statement like:
if ( (True and False) and (True and False) ) or True:
print("True because of 'or', much easier to understand")True because of 'or', much easier to understand
6.4.8The not Boolean operator¶
The not Boolean operator can be
used to negate a Boolean (i.e., take the opposite) in a conditional statement. This is useful if you need to do a quick
check for a negated condition (i.e., a False condition):
a = False
if not a:
print("a is False -> the `if` statement is True!")a is False -> the `if` statement is True!
This is equivalent to:
a = False
if a == False:
print("a is False")a is False
Both methods work! The not keyword gives you another way to test for negated (i.e., False) conditions.
6.4.9Example: Let there be light¶
The light that we see is part of the electromagnetic spectrum known as “visible light”. This visible part of the electromagnetic spectrum consists of light that has vacuum wavelengths, , between 380 nm to 700 nm. This range can be further divided up into the spectral colors:
Violet: 380 nm 450 nm
Blue: 450 nm 500 nm
Green: 500 nm 565 nm
Yellow: 565 nm 590 nm
Orange: 590 nm 625 nm
Red: 625 nm 700 nm
Using what you know about conditional code blocks, create a small Python code that
prints out the color of a user defined wavelength. For example, if we entered 600 nm as our wavelength, the Python
code would output the string 600 nm is orange light!. If the wavelength lies outside the 380 nm to 700 nm range,
have the code output the string X nm is outside the visible spectrum!, where X is the wavelength.
Solution:
We can create the necessary code by using an initial if keyword, a sequence of elif keywords, and an ending else
statement. Since each color is bounded by a minimum and maximum wavelength, the and keyword allows us to check
each color range. There are a few different ways this code can be created depending on how you use greater than or less
than operators (see our previous discussion on the bool logic class for details. One
example of implementing this program is shown below:
wavelength = 600
if (wavelength >= 380) and (wavelength < 450):
print(f"{wavelength} nm is purple light!")
elif (wavelength >= 450) and (wavelength < 500):
print(f"{wavelength} nm is blue light!")
elif (wavelength >= 500) and (wavelength < 565):
print(f"{wavelength} nm is green light!")
elif (wavelength >= 565) and (wavelength < 590):
print(f"{wavelength} nm is yellow light!")
elif (wavelength >= 590) and (wavelength < 625):
print(f"{wavelength} nm is orange light!")
elif (wavelength >= 625) and (wavelength < 700):
print(f"{wavelength} nm is red light!")
else:
print(f"{wavelength} nm is outside the visible spectrum!")600 nm is orange light!
You can also chain this another way since each conditional check goes sequentially:
wavelength = 600
if (wavelength > 700):
print(f"{wavelength} nm is outside the visible spectrum!")
elif (wavelength >= 625):
print(f"{wavelength} nm is red light!")
elif (wavelength >= 590):
print(f"{wavelength} nm is orange light!")
elif (wavelength >= 565):
print(f"{wavelength} nm is yellow light!")
elif (wavelength >= 500):
print(f"{wavelength} nm is green light!")
elif (wavelength >= 450):
print(f"{wavelength} nm is blue light!")
elif (wavelength >= 380):
print(f"{wavelength} nm is purple light!")
else:
print(f"{wavelength} nm is outside the visible spectrum!")600 nm is orange light!
Both ways work!
6.5Looping statements¶
Looping statements allow us to iterate a block of code multiple times until a condition is met. There are two common
built-in looping statements used in Python: the for statement and the while statment.
6.5.1The for statement¶
The for statement iterates over a sequence-based
object until it reaches the end of the sequence. The code below demonstrates this using a list object:
print("Iterating over list") # Start code block 1
print("[0, 1, 2, 3]") # 1
for i in [0, 1, 2, 3]: # Start code block 2
print(i) # End code 2
print("Done looping") # End code block 1Iterating over list
[0, 1, 2, 3]
0
1
2
3
Done looping
The looping code block starts with the for keyword and is followed by the command i in [0, 1, 2, 3]:, which states
two things. First, that for each element in the list [0, 1, 2, 3], we will run the subsequent code block using the
objects in the sequence. Right away we can tell the looping code block will run four times because the list has
four elements. Second, when running the looping code block, the variable i will be assigned the value of the current
element of the list. So for the first run of the looping code block i = 0 and then next loop i = 1, etc.
You can also place variables in the for loop statement:
print("Iterating over list") # Start code block 1
a = [0, 1, 2, 3] # 1
print("a:", a) # 1
# 1
for i in a: # Start code block 2
print(i) # End code 2
print("Done looping") # End code block 1Iterating over list
a: [0, 1, 2, 3]
0
1
2
3
Done looping
The iterated object does not need to be a perfect periodic sequence either. The for statement simply iterates over
all the objects in the sequence.
print("Iterating over list") # Start code block 1
a = [0, -1, 21, 3.3, "hello"] # 1
print("a:", a) # 1
# 1
for i in a: # Start code block 2
print(i) # End code 2
print("Done looping") # End code block 1Iterating over list
a: [0, -1, 21, 3.3, 'hello']
0
-1
21
3.3
hello
Done looping
It is possible to have loops nested in other loops. The example below shows how “nested” for loops can be used to
loop over two ranges:
print("Iterating two ranges") # Start code block 1
# 1
for i in range(4): # Start code block 2
print("i:", i) # 2
for b in range(3): # Start code block 3
print("b:", b) # End of code block 3
print("Looping") # 2
# End of code block 2
print("Finished") # End of code block 1Iterating two ranges
i: 0
b: 0
b: 1
b: 2
Looping
i: 1
b: 0
b: 1
b: 2
Looping
i: 2
b: 0
b: 1
b: 2
Looping
i: 3
b: 0
b: 1
b: 2
Looping
Finished
From the output of the previous cell, you can see the sub-loop for b in range(3): runs its code block entirely for
each loop of the main loop for i in range(4):. It is important to keep in mind the indentation when creating nested
loops and to use different variables for the inner loops. Using the same iterator variable can create bugs in your
code, as the variable is being modified by two different loops.
6.5.2The enumerate( ) function¶
A very useful function that can be used with for loops is the built-in
enumerate function. This function attaches an index
number to each object in an iterable list. The code below demonstrates how enumerate can be used over a list
object:
print("Iterating using an enumerated list")
for idx, i in enumerate([23, 11, 2 ,5]):
print("Index:", idx)
print("Value:", i)Iterating using an enumerated list
Index: 0
Value: 23
Index: 1
Value: 11
Index: 2
Value: 2
Index: 3
Value: 5
Our for loop statement has changed from the typical for i in [list] pattern to the enumeration pattern
for idx, i in enumerate(list). The enumerate() function will take in a sequence and return two values at each step:
(1) the index of the current element and (2) the element itself. The for idx, i in part of our statement means we are
assigning the current element index to idx and the element value to i. So, when running the first loop of the code
block we’ll have the variables idx = 0 and i = 23, and the second loop we’ll have idx = 1 and i = 11. With
enumerate() we can use the index of the current element in many ways, for example we can use the idx on another
list to get an element at the same index, and even reassign the element at the current list index:
list_a = [23,11,2,5]
list_b = [4,2,3,5]
print('Iterating over enumerated list:', list_a)
for idx, i in enumerate(list_a):
# multiply current element with element in list_b at same index
# and assign value back to list_a at same index
list_a[idx] = i * list_b[idx]
print('list_a:', list_a)Iterating over enumerated list: [23, 11, 2, 5]
list_a: [92, 22, 6, 25]
6.5.3Looping through dict objects¶
If we iterate over a dictionary object, we need to slightly change our approach:
list_a = ['a', 'b', 'c', 'd']
list_b = [4,2,3,5]
joined_dict = dict(zip(list_a, list_b))
print('Iterating over joined_dict:', joined_dict)
for i in joined_dict:
print(i)Iterating over joined_dict: {'a': 4, 'b': 2, 'c': 3, 'd': 5}
a
b
c
d
In this example we first create a dictionary by using the built-in
zip() function to join list_a and list_b together as
dict object. However, if try to iterate over the dict object, we see that only the keys are listed and not the
values. If we want to iterate through the values, we can do so in a few ways. One way is to access our dict object by
passing in the keys:
for i in joined_dict:
print('key:', i, 'value:', joined_dict[i])key: a value: 4
key: b value: 2
key: c value: 3
key: d value: 5
Or we can use the built-in .values() method that is available to dictionary objects:
for i in joined_dict.values():
print('value:', i)value: 4
value: 2
value: 3
value: 5
But perhaps more useful is the builtin method
.items() that is available for dict objects. Again,
do not worry about the details involved with using methods at this time as we will visit this concept in our
object-oriented programming lesson. The code below demonstrates how to use a for loop with a dict
object’s .items() method to display both keys and values:
for k, v in joined_dict.items():
print('key:', k, 'value:', v)key: a value: 4
key: b value: 2
key: c value: 3
key: d value: 5
The .items() method provides a set of tuples that can be iterated over in the form of (key, value). Therefore,
we use two variables k and v to represent the key and value in the statement
for k, v in joined_dict.items().
6.5.4The while loop¶
The while loop is similar to the for loop but it
iterates using a conditional statement rather than sequenced-base object. This looping structure operates until the
conditional statement is no longer true (i.e., False):
counter = 0
print("Loop until condition is false")
while counter < 5:
print(counter)
counter = counter + 1Loop until condition is false
0
1
2
3
4
The looping code block starts with the while keyword followed by the conditional statement counter < 5. This says
that the following code block will continue looping until the conditional statement is False. If the conditional
statement never becomes False, the while loop will run forever and you will need to halt / stop the kernel’s
process.
6.5.5Example: Bundling light¶
Using the example from earlier as a starting point, create a program
that reports the color of each wavelength in a list object that contains the following wavelengths:
, , , , , , and
Create two versions of this program: one that uses a for loop and one that uses a while loop.
Solution:
We can adapt the previous example’s solution for our needs by inserting it as a code block that is embedded in a
for loop or while loop. The for loop example is shown below with subsequent discussion:
wavelength = [300, 390, 400, 501, 535, 600, 732, 1000]
for i in wavelength:
if (i >= 380) and (i < 450):
print(f"{i} nm is purple light!")
elif (i >= 450) and (i < 500):
print(f"{i} nm is blue light!")
elif (i >= 500) and (i < 565):
print(f"{i} nm is green light!")
elif (i >= 565) and (i < 590):
print(f"{i} nm is yellow light!")
elif (i >= 590) and (i < 625):
print(f"{i} nm is orange light!")
elif (i >= 625) and (i < 700):
print(f"{i} nm is red light!")
else:
print(f"{i} nm is outside the visible spectrum!")300 nm is outside the visible spectrum!
390 nm is purple light!
400 nm is purple light!
501 nm is green light!
535 nm is green light!
600 nm is orange light!
732 nm is outside the visible spectrum!
1000 nm is outside the visible spectrum!
Here, we first change wavelength to now be a list and then embed the previous example’s solution inside a for
loop. Notice that we have to tab indent the if, elif, and else lines of code to have this work. In
addition, we introduce the temporary variable i that represents each value in wavelength. This is why i is
substituted into each conditional statement.
An equivalent program using the while keyword is shown below. In this version, we use i as the index number for
wavelength and set up the loop to run when i is less than the “length” of wavelength (i.e., its size / number
of entries). We use the built-in function len() it get the
size of wavelength. We enter the line i = 0 before the start of the while statement to ensure that our
loops begin at the first index position of wavelength (i.e., the zeroth position), and we include the i = i + 1
code at the end of the while block to increment along each entry.
wavelength = [300, 390, 400, 501, 535, 600, 732, 1000]
i = 0
while i < len(wavelength):
if (wavelength[i] >= 380) and (wavelength[i] < 450):
print(f"{wavelength[i]} nm is purple light!")
elif (wavelength[i] >= 450) and (wavelength[i] < 500):
print(f"{wavelength[i]} nm is blue light!")
elif (wavelength[i] >= 500) and (wavelength[i] < 565):
print(f"{wavelength[i]} nm is green light!")
elif (wavelength[i] >= 565) and (wavelength[i] < 590):
print(f"{wavelength[i]} nm is yellow light!")
elif (wavelength[i] >= 590) and (wavelength[i] < 625):
print(f"{wavelength[i]} nm is orange light!")
elif (wavelength[i] >= 625) and (wavelength[i] < 700):
print(f"{wavelength[i]} nm is red light!")
else:
print(f"{wavelength[i]} nm is outside the visible spectrum!")
i += 1300 nm is outside the visible spectrum!
390 nm is purple light!
400 nm is purple light!
501 nm is green light!
535 nm is green light!
600 nm is orange light!
732 nm is outside the visible spectrum!
1000 nm is outside the visible spectrum!
6.5.6The break and continue keywords¶
When working with looping code blocks, it can be useful to break out of an iteration cycle or an entire loop. The
break
keyword, for example, will stop running the current looping code block and return to the parent code block. The code
below demonstrates how the break keyword works:
print("Breaking out at 3")
counter = 0
while counter < 5:
if counter == 3:
break
print(counter)
counter += 1Breaking out at 3
0
1
2
Instead of breaking out of the entire loop, the
continue
keyword will skip the current iteration of the looping code block and start on the next one:
print("Skipping 3")
counter = 0
while counter < 5:
if counter == 3:
counter += 1
continue
print(counter)
counter += 1Skipping 3
0
1
2
4
All in all, both continue and break are useful keywords to use in for or while looping code blocks.
6.6List comprehension¶
List comprehension is a powerful coding
pattern when working with list objects. List comprehension allows the Python shell to “comprehend” a list by
iterating over it, doing some operation on each element, and returning a new list as an output,
all in one line.
List comprehension-based coding can be a bit hard to read at first, so let’s go over two examples. Below is an example in which a new list is created whose values are 4x greater than a starting list. Both for loop
and list comprehension versions are provided:
list_a = [0, 1, 2, 3, 4]
# Multiply each element in list_a by 4 and put into a new list
# Simple `for` loop implementation:
list_b = []
for i in list_a:
list_b.append(4*i) # List-based method that appends value to list
# List comprehension implementation:
list_c = [4*i for i in list_a]
# Display results
print("list_a:", list_a)
print("list_b:", list_b)
print("list_c:", list_c)list_a: [0, 1, 2, 3, 4]
list_b: [0, 4, 8, 12, 16]
list_c: [0, 4, 8, 12, 16]
The example above first uses a for loop code block to create a list called list_b whose values are four times of
the start list list_a. This process is repeated to create list_c, but now use list comprehension to achieve this in one line of code. The list comprehension statement, list_c = [4*i for i in list_a], does all the work of the for
loop in one line. This statement multiplies each element by 4 (4*i) for each element i in list_a and returns
the results as a new list.
The list comprehension route is a more compact way to create the new list object but it is harder to read. We can
also pair conditional statements at the end of a list comprehension statement to run an if conditional on each
element:
list_a = [0, 1, 2, 3, 4]
# Create new list of even numbers in list_a
evens = [i for i in list_a if i % 2 == 0]
print("Evens in list_a:", evens)Evens in list_a: [0, 2, 4]
As seen above, we have added a short conditional clause if i % 2 ==0 at the end of our list comprehension statement.
This conditional checks if the modulus of the element i and 2 is equal to 0. If the conditional evaluates to
True, then that element is included in the new list.
As you might guess, list comprehension and enumeration both work with dictionaries as well:
dict_a = {"a" : 0, "b" : 1, "c" : 2, "d" : 3, "e" : 4}
# Create new list of even numbers in dict_a
evens = {key:value for key, value in dict_a.items() if value % 2 == 0}
print("Evens in dict_a:", evens)Evens in dict_a: {'a': 0, 'c': 2, 'e': 4}
In this example we are using the .items() method to iterate through dict_a in a set of the (key,value). We can
filter the value with some criteria using an if statement (here we are looking for values that are even), and
then we can return the key:value for those values.
The choice on using list comprehension is up to you. It is more compact to
write, but harder to read. Code readability is critical. Some programmers will simply use a set of for and if statements instead of list comprehension. Others will include additional comments to clarify the command.
6.7Matrix operations using conditional and looping statements¶
A common application of conditional and looping statements in scientific Python is to iteratively access and operate on objects inside of lists and tuples. Rather than manually writing out each indexed value in a block of code, we can automate the process using these newly learned statements.
Let’s revisit an earlier topic about using lists to represent matrices. While we demonstrated a way to represent matrices using nested lists, we soon found out that matrix operations like matrix addition do not directly translate over to lists. Now with the knowledge of conditional and looping statements, let’s see if we can write a code block to perform this mathematical operation!
Recall that matrix addition is a cell-by-cell operation across two matrices that have the same dimensions. For a set of 3 x 2 matrices, this can be symbolically represented as:
and simple numerical example is shown below for completeness:
The cell-by-cell iterative operation lends itself to the use of for loops, specifically a nested for loop
structure in which we iterate over each row and column. The code below demonstrates how matrix addition can be
performed using conditional and looping statements on nested lists:
# matrix addition example
# initialize variables
a = [[1, 2], [3, 4], [5, 6]]
b = [[0, 3], [5, 7], [2, 1]]
c = [] # summed matrix
# addition code
if (len(a) == len(b)) and (len(a[0]) == len(b[0])):
for row in range(len(a)): # loop over all rows
summed_row = [] # variable to hold summed values for current row
for col in range(len(a[0])): # loop over all columns
value = a[row][col] + b[row][col] # actual summation for current row & col position
summed_row.append(value) # inserts value to end of summed_row
c.append(summed_row) # inserts summed row to c
print("Summed matrix:", c) # display solution
else:
print("Matrices dimensions do not match!") # error caseSummed matrix: [[1, 5], [8, 11], [7, 7]]
Even though there are 15 effective lines of code, there is a lot to take in here. Comments have been added for clarification, but let’s go over some important code blocks.
The first few lines of code,
# initialize variables
a = [[1, 2], [3, 4], [5, 6]]
b = [[0, 3], [5, 7], [2, 1]]
c = [] # summed matrixinitialize the two matrices (represented by lists a and b) to be added and a final matrix c to store added values.
Following the numerical matrix addition example from earlier, we should expect c to be equal to
[[1, 5], [8, 11], [7, 7]].
The if-else statement is technically not needed in the addition process, but we have included it to verify that
the dimensions of the two matrices are equal. There are two conditional checks in this if statement. The first
check verifies that the number of rows between a and b match. This is verified with the len(a) == len(b)
command. The second check verifies that the number of columns between a and b also match. This is verified
with the len(a[0]) == len(b[0]) command.
It is important to note that Python allows you to create nested list structures with varying sub-list length. So our conditional statements here are not the most robust checks available, but for this example they will suffice.
These two conditional checks are linked with an and boolean operator to ensure that both checks must be true in
order to allow for the addition operation. If not, the code block shifts to the else section and prints out an
error message.
Now the actual looping process begins. The primary for loop iterates over all rows with the following block of code:
for row in range(len(a)):Using the range() function based on the output of the len() function is very common in scientific Python
code, and you will probably use this structure many times throughout your career. This structure ensures
that we iterate over all rows in a (and subsequently b since they have the same dimensions). The variable row
will be incremented in each for loop cycle.
We then initialize a temporary variable called summed_row that will store the cell-by-cell additions for each row
before heading into the next for loop structure,
for col in range(len(a[0])):which iterates over all column positions in the matrices. The setup here is similar to the row iteration above but
now col will be our incremented variable over each cycle, and we use len() on the first sub-list entry in
a to get the number of columns.
The actual cell-by-cell addition occurs with the line,
value = a[row][col] + b[row][col]where value is another temporary variable. Here you can directly see how the incrementing variables row and col
are used to cycle through each cell. From there, we use the list method
.append() to insert this summed value into the temporary
list object summed_row. For our 3 x 2 matrices, the inner for loop on the column position occurs twice, so the
length of summed_row will be 2.
Once the column-based for loop completes, we again used .append() but now on c to store our two summed values
for each row. Therefore, we add the list object summed_row to c in each cycle of the main for loop (i.e., in a
row-by-row basis). This allows us to build our nested list structure for c. For our current example, this process
occurs over three iterations of the main for loop.
When the nested for loop structure is complete, we finally print out our results with the command,
print("Summed matrix:", c)and notice that we do get the correct answer!
As seen in this example, we can implement matrix operations using conditional and looping statements on nested lists. Reading nested code blocks can be difficult at times though, so while this code is serviceable, we prefer something more intuitive to implement when performing matrix operations. Thankfully, external libraries, like NumPy, exist that are specifically designed for numerical method analysis. As we will see in a later lesson about NumPy, many matrix operations are already coded into the library, so we can simply call these commands rather than writing out our own bespoke code blocks.
6.7.1Example: Matrix multiplication¶
Matrix multiplication is an important and common operation involving two matrices. This operation requires that the number of columns of the first matrix equals the number of rows of the second matrix. The resultant matrix’s (often referred to as the “matrix product”) size is based on the number of rows of the first matrix by the number of columns of the second matrix. In general, an matrix multiplied by an matrix results in a matrix product of size .
The actual “multiplication” step consists of taking the dot product between rows and columns of the two starting matrices. While writing out a general formula for very large matrices is cumbersome, for smaller matrices it is manageable. For example, the matrix multiplication of a matrix by a matrix results in a matrix with the following cells:
Using your knowledge on list representation of matrices, conditional statements, and looping statements, write a short Python code to perform matrix multiplication on the following two matrices:
The matrix product as been provided to allow you to check your code.
Solution:
One way to solve this problem is to build matrix multiplication code block using the earlier
matrix addition example as a starting point since nested for loops are needed to iterate overall
all positions. An example solution is provided below:
# matrix multiplication example
# initialize variables
d = [[1, 2, 3], [4, 5, 6]]
e = [[0, 3], [5, 7], [2, 1]]
f = [] # multiplied matrix
if (len(d[0]) == len(e)):
for row in range(len(d)): # loops over all rows in d
matrix_product_row = [] # temp variable to hold summed values for current row
for col in range(len(e[0])): # loops over all columns in e
dot_product = int() # dot product value for particular cell
for pos in range(len(d[0])):
dot_product += d[row][pos] * e[pos][col]
matrix_product_row.append(dot_product) # inserts value to end of matrix_product_row
f.append(matrix_product_row) # inserts summed row to c
print("Multiplied matrix:", f)
else:
print("Inner dimensions do not match!")Multiplied matrix: [[16, 20], [37, 53]]
The start of the code is similar to the matrix addition example in which variables are initialized and an if
statement is used to check that the “inner dimensions” of the two matrices (i.e., the column size of the first
matrix and the row size of the second matrix) match. This solution assumes that one is using list
objects as matrices so each list’s sub-list dimension is consistent with all other sub-lists.
The need to perform a dot product of the first matrix’s row with the second matrix’s column requires an additional
nested for loop. This is seen with the creation of the temporary variable dot_product and loop statement section:
for pos in range(len(d[0])):
dot_product += d[row][pos] * e[pos][col]
matrix_product_row.append(dot_product)The dot product is then stored temporarily in the list matrix_product_row until all operations are done on the
current row and then inserted into the matrix product f. In both cases the .append() method is used to insert
these values at the end of each list.
6.8Final thoughts¶
We covered many of the fundamental concepts that are needed to create more complex Python programs in this lesson.
First, we discussed how code blocks create the programmatic flow of a Python program, and how the use indentation
allow us to identify different and nested code blocks. We then covered many of the core Python statements that are used
with code blocks, such as the conditional statements if, elif, and else, and the looping statements for and
while. The lesson ended with discussions on how list comprehension can distill the logic of a multi-line for
loop in one easy to read line of code and how to use this branching code blocks to do simple matrix math. It is the
through the use of these code block-centric keywords that creates the basic structure of complex, multi-branching, and
iterative programs.