Lesson 06 - For Loops

The following topics are discussed in this notebook:

  • Looping over ranges
  • Using loops with lists
  • Looping over lists

Additional Resources

Loops

A loop is a tool that allows use to tell Python to repeat a task several times, usualy 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.

Ranges

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.

In [1]:
my_range = range(3,8)
print(type(my_range))
print(my_range)
print(list(my_range))
<class 'range'>
range(3, 8)
[3, 4, 5, 6, 7]

Looping over Ranges

We can use for loops to ask Python to repeat a task a certain number of times. The following example illustrates the basic syntax used to create a for loop.

In [2]:
for i in range(0,5):
    print("This should print 5 times.")
This should print 5 times.
This should print 5 times.
This should print 5 times.
This should print 5 times.
This should print 5 times.

At a basic level, the first line in the cell below told Python that it should execute the indented line 5 times. In truth, there is more going on under the hood of this for loop.

What is actually happening is that the variable i starts out being equal to the first value in the range provided. Each time the loop executes, i increments by 1 and the loop executes again. This process continues, with i taking on each value within the range.

Thus, in this example, the print() command executes 5 times: First with i=0, then with i=1, i=2,i=3, and finally with i=4.

As it turns out, we can access the current value of i from the body of the loop itself.

In [3]:
for i in range(0,5):
    print(i)
0
1
2
3
4
In [4]:
for i in range(0,5):
    print(i**2)
0
1
4
9
16

The example below illustrates two new ideas relating to for loops:

  1. The range over which we are looping does not have to begin with 0.
  2. We can include multiple lines of code within a for loop. Each one must be indented for the loop to recognize the code as part of the loop.
In [5]:
for i in range(1,11):
    message = "The square of " + str(i) + " is " + str(i**2) + "."
    print(message)
The square of 1 is 1.
The square of 2 is 4.
The square of 3 is 9.
The square of 4 is 16.
The square of 5 is 25.
The square of 6 is 36.
The square of 7 is 49.
The square of 8 is 64.
The square of 9 is 81.
The square of 10 is 100.

We can also use loops to alter variables that are defined outside of the loop.

In [6]:
# Sum the first 100 positive integers
total = 0
for i in range(1,101):
    total += i

print(total)
5050

The example above provides a usefull illustration of one of the ways that we can use a loop. However, we could have accomplished that particular task by using the sum() function rather than a loop.

In [7]:
print(sum(range(1,101)))
5050

� Exercise

Write a loop to find the sum of the squares of the first 50 positive integers. Store the sum in a variable called sum_of_squares. Print this variable. You should get 42925.

In [8]:
# Find the sum of the squares of the first 50 positive integers. 
sum_of_squares = 0

for i in range(1, 51):
    sum_of_squares = sum_of_squares + i**2
    
print(sum_of_squares)
42925

Using Loops to Work with Lists

One common use of a loop is to perform an action on every element of a list. In this case, we treat the variable i as an index for elements in the list.

The code in the next cell generates a random list that we will use in the following examples. You do not need to be concerned with understanding how this code works at the moment.

In [9]:
# Generate a random list of integers
import random
random.seed(1)
rand_list = random.sample(range(100), 30)
print(rand_list)
[17, 72, 97, 8, 32, 15, 63, 57, 60, 83, 48, 26, 12, 62, 3, 49, 55, 77, 0, 92, 34, 29, 75, 13, 40, 85, 2, 74, 69, 1]

We have randomly generated a list of integers called rand_list. We will now print out the square of every element in this list.

In [10]:
# print the square of each element in the rand_list

n = len(rand_list)
for i in range(0,n):
    print("The square of " + str(rand_list[i]) + " is " + str(rand_list[i] ** 2))
The square of 17 is 289
The square of 72 is 5184
The square of 97 is 9409
The square of 8 is 64
The square of 32 is 1024
The square of 15 is 225
The square of 63 is 3969
The square of 57 is 3249
The square of 60 is 3600
The square of 83 is 6889
The square of 48 is 2304
The square of 26 is 676
The square of 12 is 144
The square of 62 is 3844
The square of 3 is 9
The square of 49 is 2401
The square of 55 is 3025
The square of 77 is 5929
The square of 0 is 0
The square of 92 is 8464
The square of 34 is 1156
The square of 29 is 841
The square of 75 is 5625
The square of 13 is 169
The square of 40 is 1600
The square of 85 is 7225
The square of 2 is 4
The square of 74 is 5476
The square of 69 is 4761
The square of 1 is 1
In [11]:
# Create a list of squares of elts in rand_list

rand_squares = []  # Create a blank list.

for i in range(0, len(rand_list)):
    rand_squares.append(rand_list[i] ** 2)

print(rand_squares)
[289, 5184, 9409, 64, 1024, 225, 3969, 3249, 3600, 6889, 2304, 676, 144, 3844, 9, 2401, 3025, 5929, 0, 8464, 1156, 841, 5625, 169, 1600, 7225, 4, 5476, 4761, 1]
In [12]:
# Double all of the elements of rand_list

for i in range(0, len(rand_list)):
    rand_list[i] = rand_list[i] * 2
    
print(rand_list)
[34, 144, 194, 16, 64, 30, 126, 114, 120, 166, 96, 52, 24, 124, 6, 98, 110, 154, 0, 184, 68, 58, 150, 26, 80, 170, 4, 148, 138, 2]

� Exercise

The code in the next cell creates two randomly generated lists, listA and listB. The lists are of the same (unknown) length. In the blank cell, write code to create a third list, listC, so that for each index i, listC[i] is equal to 2 times listA[i] plus 3 times listB[i].

Print the smallest and largest elements of listC. If this was done correctly, these should be 58 and 2343.

In [13]:
random.seed(37)
size = random.choice(range(200,400))
listA = random.sample(range(500), size)
listB = random.sample(range(500), size)
In [14]:
listC = []

for i in range(0, len(listA)):
    listC.append(2 * listA[i] + 3*listB[i])
    
print(min(listC))
print(max(listC))
71
2369

Looping over Lists

In the loops that we have considered so far, we have created a temporary variable (typically called i) that runs through all of the values in a given range. We can also loop over lists by creating a temporary variable that runs through all of the values in a given list.

In [15]:
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']
print(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']
In [16]:
for movie in SW:
    print(movie)
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
In [17]:
for movie in SW:
    print(movie.title())
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

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.

Nested Loops

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.

In [18]:
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("\n")
i is equal to 0; j is equal to 0
i is equal to 0; j is equal to 1
i is equal to 0; j is equal to 2


i is equal to 1; j is equal to 0
i is equal to 1; j is equal to 1
i is equal to 1; j is equal to 2


i is equal to 2; j is equal to 0
i is equal to 2; j is equal to 1
i is equal to 2; j is equal to 2


i is equal to 3; j is equal to 0
i is equal to 3; j is equal to 1
i is equal to 3; j is equal to 2


i is equal to 4; j is equal to 0
i is equal to 4; j is equal to 1
i is equal to 4; j is equal to 2


i is equal to 5; j is equal to 0
i is equal to 5; j is equal to 1
i is equal to 5; j is equal to 2


� Excercise

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.

In [19]:
A = [ [11,12,13,14,15], [16,17,18,19,20], [21,22,23,24,25]  ]

Write a loop that prints the rows of A one at a time. This output will more closely resemble a matrix.

In [20]:
for row in A:
    print(row)
[11, 12, 13, 14, 15]
[16, 17, 18, 19, 20]
[21, 22, 23, 24, 25]

Create an empty list called ASquare. Use nested loops to turn ASquare into a matrix such that each element of ASquare is equal to the square of the corresponding element in A.

In [21]:
ASquare = []

for i in range(0,3):
    
    tempRow = []
    
    for j in range(0,5):
        tempRow.append(A[i][j] ** 2)
        
    ASquare.append(tempRow)

Print the list ASquare, one row at a time.

In [22]:
for row in ASquare:
    print(row)
[121, 144, 169, 196, 225]
[256, 289, 324, 361, 400]
[441, 484, 529, 576, 625]