Python Code Blocks: Conditional and Loop Statements
Contents
6. Python Code Blocks: Conditional and Loop Statements#
6.1. Lesson overview#
A Python code block is a section of code that runs from top to bottom, straight on through. So far all coding examples have run from top to bottom uninterrupted, so each example can be thought of as one code block:
a = 1 + 4 ### Start code block
print('a is', a) #
equal_five = (a == 5) #
print('a equals 5?', equal_five) ### End code block
a is 5
a equals 5? True
Hey! Listen!
You can use the hashtag character #
in Python to create a comment in your Python code.
Everything after the #
is ignored by the interpreter, so you can use it to put in helpful hints to understand
your code, or to make notes for yourself and others.
Definition: code block
A section of code that runs from top to bottom, straight on through.
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. In this lesson we will go over how to
create a code block in Python, and then how to use the conditional keywords (if
, elif
, and else
),
and looping keywords (for
and while
) to create code block statements.
6.2. Creating a code block#
So how do we create a code block in Python? We can use this code block as a working example:
print('Iterating over a list')
for i in [0,1,2,3]:
times_five = i * 5
print("i is ", i)
print("5 times i:", times_five)
print("End looping")
Iterating over a list
i is 0
5 times i: 0
i is 1
5 times i: 5
i is 2
5 times i: 10
i is 3
5 times i: 15
End looping
The command for i in [0,1,2,3]:
starts the code block, which is a Python statement. The statement begins with
a Python keyword, in this example we are
using thefor
keyword to create a for loop statement that iterates over a list. We will go over for
and while
loops in detail later in the lesson. We end the Python statement line with the colon character :
.
Definition: statement
A command that the Python interpreter can read and execute.
Definition: keyword
A reserved word in Python that provides special functionality.
After the for
statement, the following three lines are part of the new code block which is designated by the
indented lines of code. This indent
represents four SPACEBAR keystrokes, which is the
standard length for each indentation level. When we want to complete
the code block, we simply un-indent to match the previous code block and continue writing code. In this example, we
un-indent and type print("End looping")
back in the first code block. Below is the previous example now with
code blocks labeled in the comments:
print("Start looping over a list") #### Start code block 1
print("Here we go!") # 1
for i in [0,1,2,3]: #### Start code block 2
times_five = i * 5 # 2
print("i is ", i) # 2
print("5 times i:", times_five) #### End code block 2
# 1
print("End looping") #### End code block 1
Start looping over a list
Here we go!
i is 0
5 times i: 0
i is 1
5 times i: 5
i is 2
5 times i: 10
i is 3
5 times i: 15
End looping
Hey! Listen!
We (and the Python Software Foundation!) recommend you use four spaces using the SPACEBAR key to indent codeblocks. While you can use any number of spaces or the TAB key, four spaces is a solid style convention guideline. Your IDE, like Spyder, can set TAB to output four spaces which is a useful convenience.
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:
print('Iterating over list')
for i in [0,4,2,9]:
print(i)
Input In [4]
print(i)
^
IndentationError: expected an indented block after 'for' statement on line 2
The error message IndentationError: expected an indented block after 'for' statement on line 2
is reporting that
we forgot to indent the code block after the initial statement. Too much indenting is also a problem, as highlighted
in the code below:
print('Iterating over list')
for i in [0,4,2,9]:
print(i)
print(i*5)
Input In [5]
print(i*5)
^
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 for print(i*5)
. Indentation needs to be consistent throughout the code block.
6.3. if
and else
conditional code blocks#
The commands if
and else
are common and important keywords for code blocks starting with conditional statements. In
this section we will learn when and how to use these important keywords.
6.3.1. The 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. You can use any
number of boolean operators to create your conditional statement.
Let us change our example code so that if a
is greater than or equal to five, we multiply it by 10. Below is our
code now modified with these changes:
a = 1 + 4 #### Start code block 1
print('a is', a) # 1
equal_five = (a == 5) # 1
print('Equal 5?', equal_five) # 1
if a >= 5: #### Start code block 2
print('a >= 5') # 2
a = a * 10 #### End code block 2
# 1
print('a is', a) #### End code block 1
a is 5
Equal 5? True
a >= 5
a is 50
The if
keyword starts a conditional statement to check if a
is greater than or equal to five. If (a >= 5)
is
True
, then we proceed to code block 2, which reassigns a
to be itself multiplied by 10. However, if (a >= 5)
is
False
, then we just bypass the if
code block and print out the result. Finally, we return to code block 1 where we
print out the value of a
.
6.3.2. The else
keyword#
What if we want to divide a
by 10 when a
is not greater than or equal to five? To capture these additional
cases, we can use the else
keyword to direct the code to an alternative code block. The code below incorporates the
else
keyword to include our desired change:
a = 1 + 2 #### Start code block 1
print('a is', a) # 1
equal_five = (a == 5) # 1
print('Equal 5?', equal_five) # 1
if a >= 5: #### Start code block 2
print('a >= 5') # 2
a = a * 10 #### End code block 2
else: #### Start code block 3
print('a < 5') # 3
a = a / 10 #### End code block 3
print('a is', a) #### End code block 1
a is 3
Equal 5? False
a < 5
a is 0.3
Here, the else
keyword catches all cases when the if
clause 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.3.3. The elif
(“else if”) keyword#
What if we want our code to catch several conditionals? For instance, imagine we want our code to do something if a
is greater than 5, something else if a
is between 3 and 5, and again something entirely different for the
remaining cases?
Python can handle the need for multiple conditionals using the elif
keyword (pronounced: “else if”). This means we
can have another conditional statement to check if the initial conditional statements are False
. You can chain as
many elif
conditional code blocks as you would like.
An important 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 = 3
print('If a is 3')
if a == 3:
print('This code block will executed')
elif a > 1:
print('This code block will not be executed if a == 3, even if a > 1, because it is evaluated second')
print('But this will output if a == 2.')
If a is 3
This code block will executed
In the above example, technically both the if
and the elif
conditionals should return True
, but since the if
conditional is the first conditional evaluated True
, its code block is executed.
Now knowing how elif
works, we can now combine this conditional with our knowledge on if
and else
conditionals to
make a multiple conditional program. This is demonstrated in the code below:
a = 1 + 2 #### Start code block 1
print('a is', a) # 1
equal_five = (a == 5) # 1
print('Equal 5?', equal_five) # 1
if a >= 5: #### Start code block 2
print('a >= 5') # 2
a = a * 10 #### End code block 2
elif a > 3 and a < 5: #### Start code block 3
print('3 < a < 5') # 3
a = a - 10 #### End code block 3
else: #### Start code block 4
print('a <= 3') # 4
a = a / 10 #### End code block 4
print('a is', a) #### End code block 1
a is 3
Equal 5? False
a <= 3
a is 0.3
Notice that in the above example the elif
statement includes a conditional statement with two clauses:
elif a > 3 and a < 5:
. A conditional statement can be made up of several conditional clauses, in this case a > 3
and a < 5
, and is a useful programming technique when implementing more complex conditional statements. This is often
done using the and
and or
conditional keywords, which we will discuss in the next section.
Hey! Listen!
When comparing a variable to a range of numbers, you can also write the conditional statement as:
3 < a < 5
This is equivalent to the a > 3 and a < 5
format used in the above example.
6.3.4. The and
and or
keywords#
A conditional statement can be constructed with any number of conditional clauses chained together using the
keywords and
and or
. For example, the and
keyword 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:
a = True
b = True
print("a: ", a, "b: ", b)
if a and b:
print('a and b are both True')
else:
print('Either a or b, or both, are False')
a = False
b = True
print("a: ", a, "b: ", b)
if a and b:
print('a and b are both True')
else:
print('Either a or b, or both, are False')
a: True b: True
a and b are both True
a: False b: True
Either a or b, or both, are False
The or
keyword 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:
a = True
b = False
print("a:", a, "b:", b)
if a or b:
print('One or both of a and b are True')
else:
print('Both a and b are False')
a = False
b = False
print("a:", a, "b:", b)
if a or b:
print('One or both of a and b are True')
else:
print('Both a and b are False')
a: True b: False
One or both of a and b are True
a: False b: False
Both a and b are False
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?")
True?
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.3.5. Example: 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, \(\lambda\), between 380 nm to 700 nm. This range can be further divided up into the primary spectral colors:
Violet: 380 nm \(\le\) \(\lambda\) \(\lt\) 450 nm
Blue: 450 nm \(\lt\) \(\lambda\) \(\le\) 500 nm
Green: 500 nm \(\lt\) \(\lambda\) \(\le\) 565 nm
Yellow: 565 nm \(\lt\) \(\lambda\) \(\le\) 590 nm
Orange: 590 nm \(\lt\) \(\lambda\) \(\le\) 625 nm
Red: 625 nm \(\lt\) \(\lambda\) \(\le\) 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!
6.4. The for
and while
looping code blocks#
With conditional statements we were able to choose which code block to be executed. The Python keywordsfor
and
while
, on the other hand, will allow us to create looping statements in which can iterate a block of code multiple
times until a condition is met.
6.4.1. The for
loop#
The for
keyword iterates over a
sequence, 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 1
Iterating over list
[0,1,2,3]
0
1
2
3
done looping
The looping code block starts with the for
keyword, which is followed by i in [0,1,2,3]:
. The statement
for i in [0,1,2,3]:
says two things. First, that for each element in the list [0,1,2,3]
, we will run the code block
that follows this statement. 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.
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
for i in range(4): #### Start code block 2
# 2
print('i', i) # 2
# 2
for b in range(3): #### Start code block 3
# 3
print('b', b) #### End of code block 3
print('looping') # 2
#### End of code block 2
print('finished') #### End of code block 1
Iterating 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 parent loop for i in range(4):
. When creating multiple loops it is important to keep in mind the
indentation. Additionally, it is important 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.
A very useful function that can be used with for
loops is the
enumerate
builtin function. The code below
demonstrates how enumerate
can be used over a list
object:
print('Iterating over enumerated list')
for idx, i in enumerate([23,11,2,5]):
print('index:', idx)
print('value:', i)
Iterating over 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,
the index of the current element and 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]
If we were to iterate over a dictionary object, we would 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 builtin
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 builtin .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.4.2. The while
loop#
Using while
loops are similar to using for
loops, but instead of looping over elements in a sequence, we continue to
loop as long as a conditional statement remains True
:
print('Iterating over list')
counter = 0
while counter < 5:
print(counter)
counter = counter + 1
Iterating over list
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. When that happens, remember that you can stop or
restart the IPython kernel in JupyterLab following steps detailed earlier.
Hey! Listen!
If you are numerically modifying a variable, like adding 1 to its value, you can use the addition operator
combined with the equal sign as a shorthand (+=
). This shorthand is also possible for other operators as well:
a += 1
is the same as a = a + 1
a -= 1
is the same as a = a - 1
a *= 2
is the same as a = a * 2
a /= 2
is the same as a = a / 2
a **= 2
is the same as a = a ** 2
These shorthand formats are often used in loop structures. So in the above example, we can replace counter = counter +1
with simply counter +=1
.
6.4.3. Example: Bundling light#
Using the example from earlier as a starting point, create a program
that reports the color of each wavelength in a list
. The list
should contain the following wavelengths:
300 nm, 390 nm, 400 nm, 535 nm, 600 nm, 732 nm, and 1000 nm
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 += 1
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!
6.4.4. The 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 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 += 1
Breaking 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:
counter += 1
if counter == 3:
continue
print(counter)
Skipping 3
1
2
4
5
Hey! Listen!
What do you think would happen if the counter += 1
line in the while loop above was placed after the continue
keyword? Try it out, but do not forget about the stop button to interrupt the kernel.
All in all, both continue
and break
are useful keywords to use in for
or while
looping code blocks.
6.5. List comprehension#
List comprehension
is a powerful coding pattern when working with list
objects. List comprehension allows you 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. To demonstrate this, the example below 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
. We then repeat this process to create list_c
, but now use list
comprehension to achieve this in one line of code.
list_a = [0, 1, 2, 3, 4]
# Multiply each element in list_a by 4 and put into a new list
# for loop implementation:
list_b = []
for i in list_a:
list_b.append(i*4)
# List comprehension implementation:
list_c = [i*4 for i in list_a]
print('list_b:', list_b)
print('list_c:', list_c)
list_b: [0, 4, 8, 12, 16]
list_c: [0, 4, 8, 12, 16]
Our list comprehension statement, list_c = [i*4 for i in list_a]
, does all the work of the for
loop in one line.
In this statement, we are saying to multiply each element by 4 (i*4
) for each element i
in list_a
and return
the results as a new list. 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 clause checks if the modulus of the element i
and 2 is equal to 0, and if the clause 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.
6.6. Matrix 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. However, now with the knowledge of conditional and looping statements, we can write a code block to perform this mathematical operation!
As a review, 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 case
Summed matrix:
[[1, 5], [8, 11], [7, 7]]
Even though there is 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 matrix
initialize 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.6.1. Example: 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 m x n matrix multiplied by an n x p matrix results in a matrix product of size m x p.
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 2 x 3 matrix by a 3 x 2 matrix results in a 2 x 2 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.7. Conclusion#
In this lesson, we covered many of the fundamental concepts that are needed to create more complex Python programs.
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 a discussion on how list comprehension can distill the logic of a multi-line for
loop in one easy to read line of code. It is the through the use of these code block-centric keywords that creates
the basic structure of complex, multi-branching, and iterative programs.