Week 6
Lecture 1:
for loops over indices
range
Here is the top part of the help for range:
class range(object)
| range([start,] stop[, step]) -> range object
|
| Returns a virtual sequence of numbers from start to stop by step.
The stop value is not included.
rangeis typically used in a for loop to iterate over a sequence of numbers. Here are
some examples:
# Iterate over the numbers 0, 1, 2, 3, and 4.
for i in range(5):
# Iterate over the numbers 2, 3, and 4.
for i in range(2, 5):
# Iterate over the numbers 3, 6, 9, 12, 15, and 18.
for i in range(3, 20, 3):
Iterating over the indices of a list
Because len returns the number of items in a list, it can be used with range to
iterate over all the indices. This loop prints all the values in a list:
for i in range(len(lst)):
print(lst[i])
This also gives us flexibility to process only part of a list. For example, We can
print only the first half of the list:
for i in range(len(lst) // 2):
print(lst[i])
Or every other element:
for i in range(0, len(lst), 2):
print(lst[i])
Not "What" but "Where"
Previously, we have written loops over characters in a string or items in a list.
However, sometimes there are problems where knowing the value of the items in a
list or the characters in a string is not enough; we need to know where it occurs
(i.e. its index).
Example 1
The first example is described below:
def count_adjacent_repeats(s):
''' (str) -> int
Return the number of occurrences of a character and an adjacent
character
being the same.
>>> count_adjacent_repeats('abccdeffggh')
3
'''
repeats = 0
for i in range(len(s) - 1):
if s[i] == s[i + 1]:
repeats = repeats + 1
return repeats
We want to compare a character in the string with another character in the string
beside it. This is why we iterate over the indices because the location is important,
and only knowing the value of the character does not provide us with enough
information. This is how we are able to count repeated characters in a string. We
can't execute the body of the loop if i is len(s) - 1 because we compare to s[i +
1], and that would produce an IndexError.
Example 2
The second example is described below:
def shift_left(L):
''' (list) -> NoneType
Shift each item in L one position to the left and shift the first item
to
the last position.
Precondition: len(L) >= 1
>>> shift_left(['a', 'b', 'c', 'd'])
'''
first_item = L[0]
for i in range(len(L) - 1):
L[i] = L[i + 1]
L[-1] = first_item
For the same reasons as above, merely knowing the value of the items in the list is
not enough since we need to know where the items are located; we need to know
the index (position) of the item in the list.
LECTURE 2:
Nested Loops
Bodies of Loops
The bodies of loops can contain any statements, including other loops. When this
occurs, this is known as a nested loop.
Here is a nested loop involving 2 for loops:
for i in range(10, 13):
for j in range(1, 5):
print(i, j)
Here is the output:
10 1
10 2
10 3
10 4
11 1
11 2
11 3
11 4
12 1
12 2
12 3
12 4
Notice that when i is 10, the inner loop executes in its entirety, and only after j has
ranged from 1 through 4 is i assigned the value 11.
Example of Nested Loops
def calculate_averages(grades):
''' (list of list of number) -> list of float
Return a new list in which each item is the average of the grades in
the
inner list at the corresponding position of grades.
>>> calculate_averages([[70, 75, 80], [70, 80, 90, 100], [80, 100]])
[75.0, 85.0, 90.0]
'''
averages = []
# Calculate the average of each sublist and append it to averages.
for grades_list in grades:
# Calculate the average of grades_list.
total = 0
for mark in grades_list:
total = total + mark
averages.append(total / len(grades_list))
return averages
In calculate_averages, the outer for loop iterates through each sublist in grades.
We then calculate the average of that sublist using a nested, or inner, loop, and add
the average to the accumulator (the new list, averages).
LECTURE 3: