W04 Prepare: Lists and Repetition
During this lesson, you will learn how to store many elements in a Python list. You will learn how to write a loop that processes each element in a list. Also, you will learn that lists are passed into a function differently than numbers are passed.
Videos
Watch these videos from Microsoft about lists and repetition in Python.
Concepts
Here are the Python programming concepts and topics that you should learn during this lesson:
Lists
A Python program can store many values in a list. Lists are mutable, meaning they can be changed after they are created. Each value in a list is called an element and is stored at a unique index. An index is always an integer and determines where an element is stored in a list. The first index of a Python list is always zero (0). The following diagram shows a list that contains five strings. The diagram shows both the elements and the indexes of the list. Notice that each index is a unique integer, and that the first index is zero.
elements | "yellow" | "red" | "green" | "yellow" | "blue" |
indexes | [0] | [1] | [2] | [3] | [4] |
← list length is 5 → |
In a Python program, we can create a list by using square brackets ([ and ]). We can determine the number of items in a list by
calling the built-in len
function. We can retrieve an item from a list and replace an item in a list using square brackets
([ and ]) and an index. Example 1 contains a program that creates a list, prints the length of the list, retrieves and prints
one item from the list, changes one item in the list, and then prints the entire list.
# Example 1
def main():
# Create a list that contains five strings.
colors = ["yellow", "red", "green", "yellow", "blue"]
# Call the built-in len function
# and print the length of the list.
length = len(colors)
print(f"Number of elements: {length}")
# Print the element that is stored
# at index 2 in the colors list.
print(colors[2])
# Change the element that is stored at
# index 3 from "yellow" to "purple".
colors[3] = "purple"
# Print the entire colors list.
print(colors)
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_1.py Number of elements: 5 green ['yellow', 'red', 'green', 'purple', 'blue']
We can add an item to a list by using the insert
and append
methods. We can determine if an element is in a list by
using the Python membership operator, which is the keyword in
. We can find the index of an item within a list by using the
index
method. We can remove an item from a list by using the pop
and remove
methods. Example 2
shows how to create a list and add, find, and remove items from a list.
# Example 2
def main():
# Create an empty list that will hold fabric names.
fabrics = []
# Add three elements at the end of the fabrics list.
fabrics.append("velvet")
fabrics.append("denim")
fabrics.append("gingham")
# Insert an element at the beginning of the fabrics list.
fabrics.insert(0, "chiffon")
print(fabrics)
# Determine if gingham is in the fabrics list.
if "gingham" in fabrics:
print("gingham is in the list.")
else:
print("gingham is NOT in the list.")
# Get the index where velvet is stored in the fabrics list.
i = fabrics.index("velvet")
# Replace velvet with taffeta.
fabrics[i] = "taffeta"
# Remove the last element from the fabrics list.
fabrics.pop()
# Remove denim from the fabrics list.
fabrics.remove("denim")
# Get the length of the fabrics list and print it.
n = len(fabrics)
print(f"The fabrics list contains {n} elements.")
print(fabrics)
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_2.py ['chiffon', 'velvet', 'denim', 'gingham'] gingham is in the list. The fabrics list contains 2 elements. ['chiffon', 'taffeta']
The lists in examples 1 and 2 store strings. Of course, it is possible to store numbers in a list, too. In fact, Python allows a program to store any data type in a list, including other lists.
Repetition
A programmer can cause a computer to repeat a group of statements by writing for
and while
loops.
for loop
A for
loop iterates over a sequence, such as a list. This means a for
loop causes the computer to repeatedly execute
the statements in the body of the for
loop, once for each element in the sequence. In example 3, consider the list of colors
at line 4 and the for
loop at lines 6–7. Notice how the for
loop causes the computer to repeat
line 7 once for each element in the colors list. Of course, the code in the body of a loop can do much more with each element
than simply print it.
# Example 3
def main():
# Create a list of color names.
colors = ["red", "orange", "yellow", "green", "blue"]
# Use a for loop to print each element in the list.
for color in colors:
print(color)
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_3.py red orange yellow green blue
Notice in example 3 at lines 6–7 that just like if
statements in Python, the body of a loop starts and ends with
indentation.
range function
The Python built-in range
function creates and returns
a sequence of numbers. The range
function accepts one, two, or three parameters as shown in example 4 and its output. Many programmers use the
range
function in a for
loop to cause the computer to repeat code once for each number in a range of numbers.
Example 4 shows four for
loops that iterate over a range of numbers.
# Example 4
def main():
# Count from zero to nine by one.
for i in range(10):
print(i)
print()
# Count from five to nine by one.
for i in range(5, 10):
print(i)
print()
# Count from zero to eight by two.
for i in range(0, 10, 2):
print(i)
print()
# Count from 100 down to 70 by three.
for i in range(100, 69, -3):
print(i)
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_4.py 0 1 2 ⋮ 8 9 5 6 7 8 9 0 2 4 6 8 100 97 94 ⋮ 73 70
In example 5 at lines 6–7 and lines 11–15, there are two for
loops. Both loops print each element from
a list named colors. The first loop iterates over the elements in the colors list. The second loop uses the built-in
len
and range
functions to iterate over the indexes of the colors list. Which style of
for
loop do you prefer to read and write? Most programmers prefer to write a loop like the one at lines 6–7 because it
is simpler than the one at lines 11–15.
# Example 5
def main():
# Create a list of color names.
colors = ["red", "orange", "yellow", "green", "blue"]
# Use a for loop to print each element in the list.
for color in colors:
print(color)
print()
# Use a different for loop to
# print each element in the list.
for i in range(len(colors)):
# Use the index i to retrieve
# an element from the list.
color = colors[i]
print(color)
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_5.py red orange yellow green blue red orange yellow green blue
In the previous example, the code in the body of both for
loops is very short and simply prints one element from the list each
time through the loop. However, you can write as many lines of code as you need in the body of a loop to repeatedly perform all sorts of
computations for each element in a list.
break statement
A break
statement causes a loop to end early. In example 6 at lines 6–10, there is a for
loop that
asks the user to input ten numbers one at a time. However, the loop will terminate early if the user enters a zero (0) because of the
if
statement and break
statement at lines 8 and 9.
# Example 6
def main():
sum = 0
# Get ten or fewer numbers from the user and
# add them together.
for i in range(10):
number = float(input("Please enter a number: "))
if number == 0:
break
sum += number
# Print the sum of the numbers for the user to see.
print(f"sum: {sum}")
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_6.py Please enter a number: 6 Please enter a number: 4 Please enter a number: -2 Please enter a number: 0 sum: 8.0
while loop
A while
loop is more flexible than a for
loop and repeats while some condition is true. Imagine that we need a
function to compare the contents of two lists? Can we use a loop to compare the contents of two lists? Example 7 contains a
while
loop at lines 29–42 with an if
statement at line 35 that finds the first index where two lists
differ.
# Example 7
def main():
list1 = ["red", "orange", "yellow", "green", "blue"]
list2 = ["red", "orange", "green", "green", "blue"]
index = compare_lists(list1, list2)
if index == -1:
print("The contents of list1 and list2 are equal")
else:
print(f"list1 and list2 differ at index {index}")
def compare_lists(list1, list2):
"""Compare the contents of two lists. If the contents
of the two lists are not equal, return the index of
the first difference. If the contents of the two lists
are equal, return -1.
Parameters
list1: a list
list2: another list
Return: an index or -1
"""
# Get the length of the shortest list.
length1 = len(list1)
length2 = len(list2)
limit = min(length1, length2)
# Begin at the first index (0) and repeat until the
# computer finds two elements that are not equal or
# until the computer reaches the end of the shortest
# list, whichever comes first.
i = 0
while i < limit:
# Retrieve one element from each list.
element1 = list1[i]
element2 = list2[i]
# If the two elements are not
# equal, quit the while loop.
if element1 != element2:
break
# Add one to the index variable.
i += 1
# If the length of both lists are equal and the
# computer verified that all elements are equal,
# set i to -1 to indicate that the contents of
# the two lists are equal.
if length1 == length2 == i:
i = -1
return i
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_7.py list1 and list2 differ at index 2
Compound Lists
A compound list is a list that contains other lists. Compound lists are used to store lots of related data. Example 8 shows how to create a compound list, retrieve one inner list from the compound list, and retrieve an individual number from the inner list.
# Example 8
def main():
# These are the indexes of each
# element in the inner lists.
YEAR_PLANTED_INDEX = 0
HEIGHT_INDEX = 1
GIRTH_INDEX = 2
FRUIT_AMOUNT_INDEX = 3
# Create a compound list that stores inner lists.
apple_tree_data = [
# [year_planted, height, girth, fruit_amount]
[2012, 2.7, 3.6, 70.5],
[2012, 2.4, 3.7, 81.3],
[2015, 2.3, 3.6, 62.7],
[2016, 2.1, 2.7, 42.1]
]
# Retrieve one inner list from the compound list.
one_tree = apple_tree_data[2]
# Retrieve one value from the inner list.
height = one_tree[HEIGHT_INDEX]
# Print the tree's height.
print(f"height: {height}")
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_8.py height: 2.3
Example 9 shows how to process all elements in a compound list. The for
loop at line 20 causes the computer to repeat
lines 21–27 once for each inner list that is inside the compound list named apple_tree_data
. Line 23 retrieves
the fruit amount from one inner list and then line 27 adds one fruit amount to the total fruit amount.
# Example 9
def main():
# These are the indexes of each
# element in the inner lists.
YEAR_PLANTED_INDEX = 0
HEIGHT_INDEX = 1
GIRTH_INDEX = 2
FRUIT_AMOUNT_INDEX = 3
# Create a compound list that stores inner lists.
apple_tree_data = [
# [year_planted, height, girth, fruit_amount]
[2012, 2.7, 3.6, 70.5],
[2012, 2.4, 3.7, 81.3],
[2015, 2.3, 3.6, 62.7],
[2016, 2.1, 2.7, 42.1]
]
total_fruit_amount = 0
# This loop will repeat once for each inner list
# in the apple_tree_data compound list.
for inner_list in apple_tree_data:
# Retrieve the fruit amount from
# the current inner list.
fruit_amount = inner_list[FRUIT_AMOUNT_INDEX]
# Print the fruit amount for the current tree.
print(fruit_amount)
# Add the current fruit amount to the total.
total_fruit_amount += fruit_amount
# Print the total fruit amount.
print(f"Total fruit amount: {total_fruit_amount:.1f}")
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_9.py 70.5 81.3 62.7 42.1 Total fruit amount: 256.6
Values and References
In a Python program, the computer assigns values to variables differently based on their data type. Consider the small program in example 10 and the output of that program. The program in example 10 contains two integer variables named x and y. The program in example 10 does the following:
-
The statement at line 3 stores the value 17 into the variable x.
-
Line 4 copies the value that is in the variable x into the variable y.
-
Line 5 prints the values of x and y which are both 17.
-
Line 6 adds one to the value of x, making its value 18 instead of 17.
-
Line 7 prints the values of x and y again. The value of x was changed to 18. The value of y remained unchanged.
Why does line 6 (x += 1
) change the value of x but not change the value of y ? Because
line 4 copies the value that was in x into y. In other words, x and y are two
separate variables, each with its own value.
# Example 10
def main():
x = 17
y = x
print(f"Before changing x: x {x} y {y}")
x += 1
print(f"After changing x: x {x} y {y}")
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_10.py Before changing x: x 17 y 17 After changing x: x 18 y 17
Example 11 shows a small Python program that contains two variables named lx and ly that each refer to a list. This program is similar to the previous program, but it has two lists instead of two integers. From the output of example 11, we see there is a big difference between the way a Python program assigns integers and the way it assigns lists. The program in example 11 does the following:
-
The statement at line 3 creates a list and stores a reference to that list in the variable lx.
-
Line 4 copies the reference in the variable lx into the variable ly. Line 4 does not create a copy of the list but instead causes both the variables lx and ly to refer to the same list.
-
Line 5 prints the values of lx and ly. Notice that their values are the same as we expect them to be because of line 5.
-
Line 6 appends the number 5 onto the list lx.
-
Line 7 prints the values of lx and ly again. Notice in the output that when lx and ly are printed the second time, it appears that the number 5 was appended to both lists.
Why does it appear that appending the number 5 onto lx also appends the number 5 onto ly ? Because lx and ly refer to the same list. There is really only one list with two references to that list. Because lx and ly refer to the same list, a change to the list through variable lx can be seen through variable ly.
# Example 11
def main():
lx = [7, -2]
ly = lx
print(f"Before changing lx: lx {lx} ly {ly}")
lx.append(5)
print(f"After changing lx: lx {lx} ly {ly}")
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_11.py Before changing lx: lx [7, -2] ly [7, -2] After changing lx: lx [7, -2, 5] ly [7, -2, 5]
From examples 10 and 11, we learn that when a computer executes a Python statement to assign the value of a boolean, integer, or
float variable to another variable (y = x
), the computer copies the value of one variable into the other. However, when
a computer executes a Python statement to assign the value of a list variable to another variable (ly = lx
), the computer does
not copy the value but instead copies the reference so that both variables refer to the same list in memory.
Pass by Value and Pass by Reference
The fact that the computer copies the value of some data types (boolean, integer, float) and copies the reference for other data types (list
and other large data types) has important implications for passing arguments into functions. Consider the Python program in example 12
with two functions named main
and modify_args
. The program in example 12 does the following:
-
The statement at line 4 assigns the value 5 to a variable named x.
-
Line 5 assigns a list to a variable named lx.
-
Line 6 prints the values of x and lx before they are passed to the modify_args function.
-
Line 9 calls the
modify_args
function and passes x and lx to that function. -
Within the
modify_args
function, line 22 changes the value of the parameter n by adding one to it, and line 23 changes the value of the parameter alist by appending the number 4 onto it. -
Line 10 prints the values of x and lx after they were passed to the
modify_args
function. Notice in the output below that the value of x was not changed by themodify_args
function. However, the value of lx was changed by themodify_args
function.
# Example 12
def main():
print("main()")
x = 5
lx = [7, -2]
print(f"Before calling modify_args(): x {x} lx {lx}")
# Pass one integer and one list
# to the modify_args function.
modify_args(x, lx)
print(f"After calling modify_args(): x {x} lx {lx}")
def modify_args(n, alist):
"""Demonstrate that the computer passes a value
for integers and passes a reference for lists.
Parameters
n: A number
alist: A list
Return: nothing
"""
print(" modify_args(n, alist)")
print(f" Before changing n and alist: n {n} alist {alist}")
# Change the values of both parameters.
n += 1
alist.append(4)
print(f" After changing n and alist: n {n} alist {alist}")
# Call main to start this program.
if __name__ == "__main__":
main()
> python example_12.py main() Before calling modify_args(): x 5 lx [7, -2] modify_args(n, alist) Before changing n and alist: n 5 alist [7, -2] After changing n and alist: n 6 alist [7, -2, 4] After calling modify_args(): x 5 lx [7, -2, 4]
From the output of example 12, we see that modifying an integer parameter changes the integer within the called function only. However, modifying a list parameter changes the list within the called function and within the calling function. Why? Because when a computer passes a boolean, integer, or float variable to a function, the computer copies the value of that variable into the parameter of the called function. Copying the value of an argument into a parameter is known as pass by value. However, when a computer passes a list variable to a function, the computer copies the reference so that the original variable and the parameter both refer to the same list in memory. Copying the reference of an argument into a parameter is known as pass by reference.
Rationale for Pass by Reference
Why are booleans and numbers passed to a function by value and lists are passed to a function by reference? To understand the answer to this question, consider the work a computer would have to do if lists were passed by value.
When a computer passes a number (or boolean) variable to a function, the number is passed by value which means the computer copies the value of the number variable into the parameter of the called function. This works well for numbers because each number variable occupies a small amount of the computer’s memory. Making a copy of a number is fast, and the copy uses a small amount of memory.
However, a list may contain millions of elements and therefore occupy a large amount of the computer’s memory. If lists were passed by value to a function, the computer would have to make a copy of a list each time it is passed to a function. If a list is large, copying the list takes a relatively long time and uses a lot of the computer’s memory for the copy. Therefore, to make programs fast and use less memory, lists (and other large data types) are passed to a function by reference.
Tutorials
If the concepts in this preparation content seem confusing to you, reading these tutorials may help you better understand the concepts.
Summary
During this lesson, you are learning how to store many values in a list. Each element in a list is stored at a unique index. Each index is an
integer, and the first index in a Python list is always zero (0). The built-in len
function will return the number of elements
stored in a list. The index of the last element in a Python list is always one less than the length of the list. To retrieve or store one
element in a list, you can use the square brackets ([ and ]) and an index. To process all the elements in a list, you can write a
for
loop. A compound list is a list that stores smaller lists.
During this lesson, you are also learning the difference between passing arguments into a function by value and by reference. Numbers are passed into a function by value, meaning that the computer copies the number from an argument into a parameter. Lists are passed into a function by reference, meaning the computer does not make a copy of a list argument but instead passes a reference to the list into a called function. Because lists are passed by reference, if a called function changes a list that is a parameter, that function is not changing a copy of the list but instead is changing the original list from the calling function.
Checkpoint
Purpose
Reinforce your understanding that numbers are passed to a function by value and lists are passed to a function by reference.
Problem Statement
Within a Python program, when a number is passed as an argument to a function, the computer copies the number from the argument into the parameter. In other words, the parameter gets a copy of the value that is in the argument. However, when a list is passed as an argument to a function, the computer does not copy the list. Instead, the computer copies a reference to the list into the parameter. This means the argument and parameter refer to the same list. If a called function changes a list that was passed to the function, this will change the list in both the calling and called functions because both the argument and parameter refer to the same list.
Assignment
During this checkpoint, you will examine and run a Python program that passes both a number and a list to function. Do the following:
-
Download and save the pass_args.py Python file and then open it in VS Code.
-
Run the
pass_args.py
program on your computer. Examine the code and the output and answer the following three questions:-
In
main
, there are two local variables named x and lx. At line 14, both of these local variables are passed to themodify_args
function. After the call tomodify_args
finished, which ofmain
’s two local variables did themodify_args
function change?-
x
-
lx
-
both of them
-
neither of them
-
-
Why is the
modify_args
function NOT able to changemain
’s local variable x?-
Because x is a number and therefore passed to a function by value
-
Because x is a list and therefore passed to a function by reference
-
-
Why is the
modify_args
function able to changemain
’s local variable lx?-
Because lx is a number and therefore passed to a function by value
-
Because lx is a list and therefore passed to a function by reference
-
-
Sample Run
> python pass_args.py main() Before calling modify_args(): x 5 lx [7, -2] modify_args(n, alist) Before changing n and alist: n 5 alist [7, -2] After changing n and alist: n 6 alist [7, -2, 4] After calling modify_args(): x 5 lx [7, -2, 4]
Up Next
- W04 Prepare 2: Dictionaries
Other Links:
- Return to: Week Overview | Course Home