Looping, like lists, is a critical component in programming and data science. When we're training models on data, we'll need to loop over each data point, examining it in turn and adjusting our model accordingly regardless of how many data points there are. This kind of repetitive task is ideal for looping.
Let's define for ourselves the following list:
In [4]:
ages = [21, 22, 19, 19, 22, 21, 22, 31]
This is a list containing the ages of some group of students, and we want to compute the average. How do we compute averages?
We know an average is some total quantity divided by number of elements. Well, the latter is easy enough to compute:
In [7]:
number_of_elements = len(ages)
print(number_of_elements)
The total quantity is a bit trickier. You could certainly sum them all manually--
In [5]:
age_sum = ages[0] + ages[1] + ages[2] # + ... and so on
...but that seems really, really tedious. Plus, how do you even know how many elements your list has?
The structure itself is pretty simple:
Let's start simple: looping through a list, printing out each item one at a time.
In [1]:
for N in [2, 5, 7, 9]: # Header
print(N) # Body
There are two main parts to the loop: the header and the body.
N
).Back, then, to computing an average:
In [8]:
age_sum = 0
ages = [21, 22, 19, 19, 22, 21, 22, 31]
for age in ages:
age_sum += age
avg = age_sum / number_of_elements # Compute the average using the formula we know and love!
print("Average age: {:.2f}".format(avg))
You can loop through sets and tuples the same way.
In [36]:
s = set([1, 1, 2, 3, 5])
for item in s:
print(item)
In [37]:
t = tuple([1, 1, 2, 3, 5])
for item in t:
print(item)
The unifying theme with all these collections you can loop through is that they're all examples of iterators.
Easily the most common iterator you'll use (aside from lists, sets, and tuples) is the range
function:
In [2]:
for i in range(10):
print(i, end = " ") # Prints everything on 1 line.
Note, again, that the range of numbers goes from 0 (inclusive) to the specified end (exclusive)! The critical point is that the argument to range
specifies the length of the returned iterator.
A few more examples of range
before we get back to loops:
In [3]:
for i in range(5): # One argument: specifies the "end"
print(i, end = " ")
In [4]:
for i in range(5, 10): # Two arguments: first is "start" (inclusive), second is "end" (exclusive)
print(i, end = " ")
In [5]:
for i in range(0, 10, 2): # Three arguments: start, end, and increment
print(i, end = " ")
IMPORTANT: INDENTATION MATTERS
You'll notice in these loops that the loop body is distinctly indented relative to the loop header. This is intentional and is indeed how it works! If you fail to indent the body of the loop, Python will complain:
In [48]:
some_list = [3.14159, "random stuff", 4200]
for item in some_list:
print(item)
With loops, whitespace in Python really starts to matter. If you want many things to happen inside of a loop, you'll need to indent every line!
Let's say in some future homework assignment, I ask you to write a loop computing the squares of the numbers 1-10. How would you do it?
Well, you could manually write it out, I suppose...
In [39]:
squares = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
...but that's awfully boring.
Instead, let's use the range
function we were just discussing:
In [9]:
squares = [] # Empty list for all our squares
for num in range(10):
squared_number = num ** 2 # Exponent operation!
squares.append(squared_number) # Add to our list.
print(squares)
This gets its own subsection because it pulls together pretty much all the concepts we've discussed so far: lists, tuples, dictionaries, and looping.
Let's start by defining a dictionary. In this case, we'll set up a dictionary that maps people to their favorite programming language.
In [43]:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'shannon': 'python'
}
# Notice the indentation, if you decide to define a dictionary this way!
Remember the super-useful methods for iterating through dictionaries? keys
gives you a list of all the keys, values
a list of all the values, and items
a list of tuples of the key-value pairs. Here's the loop:
In [44]:
for key, value in favorite_languages.items(): # 1
print("{} prefers {}.".format(key, value))
1: Notice how key, value
are just out there floating! This is called unpacking and is a very useful technique in Python. If I have a list of a few items, and (critically) I know how many items there are, I can do this
In [45]:
some_list = ['a', 'b']
a, b = some_list
instead of this
In [46]:
some_list = ['a', 'b']
a = some_list[0]
b = some_list[1]
In the same vein, I could have just as easily written the loop like this:
In [47]:
for keyvalue in favorite_languages.items(): # 1
key = keyvalue[0]
value = keyvalue[1]
print("{} prefers {}.".format(key, value)) # 2
and indeed, if that is easier for you to understand, by all means do it! This is to illustrate all the concepts at play at once:
favorite_languages.items()
items()
provides a tuple: a key-value pair from the dictionaryThat's pretty much for
loops!
What about the case where you don't know ahead of time how many iterations your loop will take?
"While" loops go back yet again to the concept of boolean logic we introduced in an earlier lecture: loop until some condition is reached.
The structure here is a little different than for
loops. Instead of explicitly looping over an iterator, you'll set some condition that evaluates to either True
or False
; as long as the condition is True
, Python executes another loop.
In [6]:
x = 10
while x < 15:
print(x, end = " ")
x += 1
x < 15
is a boolean statement: it is either True
or False
, depending on the value of x
. Initially, this number is 10, which is certainly < 15
, so the loop executes. 10 is printed, x
is incremented, and the condition is checked again.
A potential downside of while
loops: forgetting to update the condition inside the loop.
It's easy to take for granted; for
loops implicitly handle this for us!
In [7]:
for i in range(10, 15):
print(i, end = " ")
# No update needed!
Use for
loops frequently enough, and when you occasionally use a while
loop, you'll forget you need to update the loop condition.
Some questions to discuss and consider:
1: Using the awful matrix construct of a "list of lists," show how you could write loops that double the value of each element of the matrix.
2: for
and while
loops may have different syntax and different use cases, but you can often translate the same task between the two types of loops. Show how you could use a while
loop to iterate through a list of numbers from range()
.
3: Let's say you have two lists, K
and V
, that are both the same length. Show how, using only 1 loop, you can loop through both of them simultaneously.
4: Now let's say your lists K
and V
are not the same length. Using 1 loop, iterate through them, stopping when you reach the end of the shorter list.
A1 is out!
Even though A0 isn't "graded", please submit by 11:59 tonight.
Next week: generators and comprehensions and enumerate
, oh my!