- Review the basic idea of
`for`loops, and discuss other potential used of`for`loops - Part 1: Ranges and their use in
`for`loops - Part 2:
`for`loops that do not use all of the indices - Part 3: Nested
`for`loops and images

Reading: *Practical Programming*, Section 7.1 and the start of 7.2.

So far we have used for loops to access each entry in a list or input file in succession and apply one or more operations to each.

Example 1 (from Lecture 7):

co2_levels = [ 320.03, 322.16, 328.07, 333.91, 341.47, 348.92, 357.29, 363.77, 371.51, 382.47, 392.95 ] avg = sum(co2_levels) / len(co2_levels) for value in co2_levels: diff = value - avg print 'Difference from average is %.2f' %diff, 'ppm'

Example 2 (from HW 3):

# Access the file containing the valid words words_file = open('words.txt') # Read each word, remove the white space and the \n and append it to the list words_list = [] for w in words_file: w = w.strip().strip('\n') words_list.append(w)

Example 3 (also from Lecture 1):

def three_double(s): for i in range(0, len(s)-5): if s[i] == s[i+1] and s[i+2] == s[i+3] and s[i+4] == s[i+5]: return True return False

- Output the year associated with each CO2 level. This requires knowing the position of each value the list
- Look for trends in the data: compare value for current year with value for a previous year.
- Access data from multiple lists in the same loop.
- Look at combinations of values.
- Loop over two-dimensional (image) data.

We already started using ranges in HW 3, but we will go over them in detail here.

A range is a function to generate a list of integers. For example,

>>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Notice this is up through and

**not including**the last value specified!If we want to start with something other than 0, we provide the starting values

>>> range(3,8) [3, 4, 5, 6, 7]

We can create increments. For example,

>>> range(4,20,3) [4, 7, 10, 13, 16, 19]

starts at 4, increments by 3, stops when 20 is reached or surpassed.

We can create backwards increments

>>> range(-1, -10, -1) [-1, -2, -3, -4, -5, -6, -7, -8, -9]

We can use the

`range`to generate the list of values in a for loop. Our first example is printing the contents of the`planets`listplanets = [ 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto' ] for i in range(len(planets)): print planets[i]

The variable

`i`is variously known as the “index” or the “loop index variable” or the “subscript”.We will modify the loop in class to do the following:

- Print the indices of the planets (starting at 1!)
- Print the planets backward.
- Print every other planet.

Generate a range for the positive integers less than 100. Use this to calculate the sum of these values, with and without a for loop.

Use a range and a for loop to print the even numbers less than a given integer

`n`.The years for the CO2 levels were in parts per million every 5 years starting in 1960. Generate a range based on this and on the length of

`co2_levels`. Assign the resulting list to the variable`year`.Suppose we want a list of the squares of the digits 0..9. The following does NOT work

squares = range(10) for s in squares: s = s*s

Why not? Write a different for loop that uses indexing into the

`squares`list to accomplish our goal.

- Accessing multiple lists in one for loop
- Stopping before the end of a list
- Comparing adjacent values in a list

These types of operations are used over and over again in different programming problems.

We can use our generated list,

`years`, from the third exercise just above, to solve the problem of printing both the year and the CO2 level.for i in range(len(co2_levels)): print "Year %d: CO2 level %.2f" %(years[i], co2_levels[i])

Notice that we created a second range of indices and used these to index

**both**`years`and`co2_levels`.We can solve the same problem without using the

`years`range, as infor i in range(len(co2_levels)): print "Year %d: CO2 level %.2f" %(1960 + i*5, co2_levels[i])

Sometimes the loop index should not go over the entire range of indices, and we need to think about where to stop it “early”, as the next two examples show.

Example 1: We’d like to count how many years the CO2 level has risen relative to the previous five years. We’ll write a simple loop to do this.

Example 2: Returning to our example from Lecture 1 and HW 3, we will briefly re-examine our solution to the following problem: Given a string, how can we write a function that decides if it has three consecutive double letters?

def has_three_doubles(s): for i in range(0, len(s)-5): if s[i] == s[i+1] and s[i+2] == s[i+3] and s[i+4] == s[i+5]: return True return False

In each case, we have to think carefully about where to start our looping and where to stop!

The following code for finding out if a word has two consecutive double letters is wrong. Why? When, specifically, does it fail?

def has_two_doubles(s): for i in range(0, len(s)-5): if s[i] == s[i+1] and s[i+2] == s[i+3]: return True return False

A local maximum, or peak, in a list is a value that is larger than the values next to it. For example,

L = [ 10, 3, 4, 9, 19, 12, 15, 18, 15, 11, 14 ]

has local maxima at indices 4 and 7. (Note that the beginning and end values are not considered local maxima.) Write code to print the index and the value of each local maximum.

Some problems require “iterating” over either

- two dimensions of data, or
- all pairs of values from a list

As an example, here is code to print all of the products of digits:

digits = range(10) for i in digits: for j in digits: print "%d x %d = %d" %(i,j,i*j)

How does this work?

- for each value of i — the variable in the first, or “outer”, loop,
- Python executes the
*entire*second, or “inner”, loop

We will look at finding the two closest points in a list...

A

*tuple*is simply a list that can not be changed, e.g.>>> x = (4, 5, 10) # note the parentheses rather than [ ] >>> print x[0] 4 >>> print x[2] 10

A list can be converted to a tuple:

>>> L = [ 'a', 6 ] >>> T = tuple(L) # T is a copy of L that can not be changed. >>> print T[0] a >>> L[0] = 'b' >>> print L[0] # The original list is changed. b >>> print T[0] # The tuple created from the list has not. a

Suppose we are given a list of point locations in two dimensions, where each point is a tuple. For example,

points = [ (1,5), (13.5, 9), (10, 5), (8, 2), (16,3) ]

Our problem is to find the two points that are closest to each other.

The natural idea is to compute the distance between any two points and find the minimum.

- We can do this with and without using a list of distances.

We will work through the approach to this and post the result on the Piazza site.

The following simple exercise will help you understand loops better. Show the output of each of the following pairs of

`for`loops. The first two pairs are nested loops, and the third pair is formed by consecutive, or “sequential”, loops.# Version 1 sum = 0 for i in range(10): for j in range(10): sum += 1 print sum

# Version 2 sum = 0 for i in range(10): for j in range(i+1,10): sum += 1 print sum

# Version 3 sum = 0 for i in range(10): sum += 1 for j in range(10): sum += 1 print sum

`range`is used to generate a list of indices in a`for`loop- Indices in a
`for`loop can be used to access and change the contents of a list. - The indices in a for loop can be used to access two or more different lists.
- Changing the range of indices allows us to control how we access
values in a
`for`loop. - Nested for loops can be used to access two-dimensional data or compute properties of all pairs of values in a list.