A loop is a tool that allows us to instruct Python to repeat a task several times, usually with slight variations each time. We will consider two types of loops in this course: for loops and while loops.
We will begin with for loops, but before we can do so, we need to introduce the concept of a range.
The range(a, b)
function generates a list of integers beginning with a
and continuing up to, but NOT INCLUDING b
.
A range is not a list, but can be converted into a list.
my_range = range(3,8)
print(type(my_range))
print(my_range)
print(list(my_range))
We can use for loops to ask Python to repeat a task a certain number of times. The syntax for constructing a for loop is as follows:
for i in range(a,b): # Body of for loop
This code asks Python to execute the body of the for loop 5 times - once for each integer in the specified range. The variable i
is referred to as a loop counter. The counter will have a value of a
during the first iteration of the loop, and will increment at the start of each new iteration.
for i in range(0,5):
print('The value of i is', i)
The code in the cell above is equivalent to that in cell below. Notice that using a for loop for this task is much more concise.
i = 0
print('The value of i is', i)
i = 1
print('The value of i is', i)
i = 2
print('The value of i is', i)
i = 3
print('The value of i is', i)
i = 4
print('The value of i is', i)
Note the following five points regarding for
loops:
for
statement. These ideas are all illustrated in the following example, which prints the squares of the first 10 positive integers.
for n in range(1,11):
message = "The square of " + str(n) + " is " + str(n**2) + "."
print(message)
We can also use loops to alter variables that are defined outside of the loop. This is useful for calculating running totals. The code in the cell below calculates the sum of the squares of the first 100 integers. That is, it calculates $1^2 + 2^2 + 3^2 + ... + 99^2 + 100^2$.
# Sum the first 100 positive integers
total = 0
for i in range(1,101):
total += i**2
print(total)
One common use of a loop is to perform an action on every element of a list. In this case, we typically use the loop counter as an index for elements in the list.
The list below contains 30 integer values, several of which are negative.
big_list = [ 17, -72, 97, -18, 32, -15, -63, -57, 40, 83,
-48, 26, 12, -62, 16, 49, 55, -77, -30, 92,
34, -29, -75, 13, 40, -85, 62, -74, -69, -31]
Assume that we wish to sum the absolute values of the numbers in big_list
. We can do so using a for loop and the abs()
value function.
total = 0
for i in range(0, len(big_list)):
total += abs(big_list[i])
print(total)
There are occasions when we might want to create a new list based on the values in one or more already existing lists. Depending on the task, we might be able to accomplish it by starting with an empty list, and then appending elements to it as we loop over another list.
As an example, assume that we have been provided with two equally sized lists, listA
and listB
, as follows:
listA = [13, 18, 23, 42, 27, 22, 36, 17, 44, 34, 35, 33, 41, 43, 12, 45, 29, 37, 14, 15]
listB = [42, 14, 31, 39, 40, 48, 47, 36, 28, 32, 11, 27, 16, 17, 34, 33, 46, 22, 26, 15]
Assume that we need to create a new list, listC
, that has the same number of elements as listA
and listB
, such that an particular element in listC
is the sum of the numbers with the same index in listA
and listB
. The cell below includes code for accomplishing such a task.
listC = []
M = min(len(listA), len(listB))
for i in range(0, M):
temp = listA[i] + listB[i]
listC.append(temp)
print(listC)
In the for
loops that we have seen so far, we have specifed a range, and then a counter that iterated through all of the values in that range. Python provides us with another technique for looping over a list. If we replace the range in our loop statement with a list, then the loop counter will iterate over items in the list, rather than elements in a range.
For an example, consider the following three cells.
SW = ['the phantom menace', 'attack of the clones', 'revenge of the sith',
'a new hope', 'the empire strikes back','return of the jedi',
'the force awakens']
The cell below loops over the list SW
, printing each element. During the first iteration of the loop, the counter movie
will be equal to the first element of SW
, during the second iteration, movie
will be equal to the second element, and so on.
for movie in SW:
print(movie)
for movie in SW:
print(movie.title())
It should be noted that this method of looping does not provide any new functionality. In fact, losing access to the index actually limits the applications that we can use a loop for. However, looping over a list directly can be a convenient shortcut for reading the elements of a list when we don't need to make any changes to the list and don't need care about the indices of the elements in the list.
For some complex tasks, it is necessary to include loops inside of other loops. This is called a nested loop. The simplest case of a nested loops is when we have one loop that itself contains another loop. In this case, we call the first loop that Python encounters the outer loop, and the loop inside of that is called the inner loop. Each time the outer loop runs, the entire inner loop will process, running through all of it's possible iterations.
To get an introduction to how nested loops work, consider the following example.
for i in range(0, 6):
for j in range(0, 3):
print("i is equal to " + str(i) + "; j is equal to " + str(j))
print()
The following cell contains a list of lists, named A
. This list is intended to represent a 3x5 matrix. Each of the three lists inside A
represents a single row with 5 elements.
A = [ [11,12,13,14,15], [16,17,18,19,20], [21,22,23,24,25] ]
The cell below prints the rows of A
one at a time. This output will more closely resemble a matrix.
for row in A:
print(row)
Assume that we wish to create a new list called ASquare
. This list should also represent a 3x5 matrix, and each element of ASquare
should be the square of the corresponding element of A
. This will require two loops. The first loop will loop over the rows of A
. The second loop will loop over the elements of a given row.
ASquare = []
for i in range(0,len(A)):
tempRow = []
for j in range(0,len(A[i])):
tempRow.append(A[i][j] ** 2)
ASquare.append(tempRow)
Notice that we build up each row in ASquare
one element at a time, and when we are finished with a row, we add that to ASquare
. We will now print the rows of ASquare
.
for row in ASquare:
print(row)
Assume that a company called WidgCo manufactures and sells many different varieties of widgets. In the cell below, four lists are created to contain information about WidgCo's annual sales.
prodID
is a list that contains the product ID for each variety of widget produced.units
is a list containing the number of widgets sold of each type during the previous year. unit_price
is a list containing the price per widget for which WidgCo sells each widget type. unit_cost
is a list containing the cost to WidgCo for producint a single widget of each type. import random
random.seed(37)
n = random.choice(range(200,400))
prodID = list(range(101, 101+n))
units = random.choices(range(100,300), k=n)
unit_price = random.choices(range(20,50), k=n)
unit_cost = random.choices(range(5,10), k=n)
The lists in the cell above are generated at random, and have an unknown size. However, each list is the same size, and for any given index i
, the elements of the four lists at that particular index will all refer to the same type of widget.
In the cell below, we print the information for the first five product types. We will print the information in a tabular format.
print('prodID\t units\t price\t cost')
print('-----------------------------')
for i in range(0,5):
print(prodID[i], '\t', units[i], '\t',
unit_price[i], '\t', unit_cost[i])
We now create three new lists called revenue
, cost
, and profit
.
revenue
will contain the total annual revenue generated by each type of widget.cost
will contain the total annual costs incurred by producing each type of widget.profit
will contain the total annual profit generated by each type of widget.revenue = []
cost = []
profit = []
for i in range(0, len(prodID)):
revenue.append( units[i] * unit_price[i])
cost.append( units[i] * unit_cost[i] )
profit.append( revenue[i] - cost[i] )
In the cell below, we calculate the total annual revenue, total annual cost, and total annual profit for WidCo.
total_revenue = sum(revenue)
total_cost = sum(cost)
total_profit = sum(profit)
print('Revenue:', total_revenue)
print('Cost: ', total_cost)
print('Profit: ', total_profit)
Assume that we are asked to determine which product generated the greatest profit during the previous year. We can accomplish that using the max()
function and the index()
method.
max_profit = max(profit)
idx = profit.index(max_profit)
print('prodID: ', prodID[idx])
print('units: ', units[idx])
print('unit_price:', unit_price[idx])
print('unit_cost: ', unit_cost[idx])
print('profit: ', profit[idx])
Python creates a shortcut for iteratively creating lists. This shortcut is called a list comprehension. We know that we can create a list iteratively using a for loop as follows:
my_list = []
for i in range(a,b):
value = whatever
my_list.append(value)
The same result can be obtained in a more compact fashion using a list comprehension as follows:
my_list = [value for i in range(a,b)]
Lets see a few examples. In the first example, we will create a list containing the square of all elements in a range.
sq_list = [n**2 for n in range(1,10)]
print(sq_list)
In a previous example, we were given lists listA
and listB
, and were asked to create a list listC
that contained an elementwise sum of the listA
and listB
. Let's see how this could be accomplished with a list comprehension.
listA = [13, 18, 23, 42, 27, 22, 36, 17, 44, 34, 35, 33, 41, 43, 12, 45, 29, 37, 14, 15]
listB = [42, 14, 31, 39, 40, 48, 47, 36, 28, 32, 11, 27, 16, 17, 34, 33, 46, 22, 26, 15]
listC = [listA[i] + listB[i] for i in range(0, len(listA))]
print(listC)