For Loops¶

Goal: Convert Temperatures¶

  • Make a temperature conversion chart, from Fahrenheit to Centigrade, for these Fahrenheit values: 30, 40, 50, 60, 70.
  • Output (approximate):
30 -1.1111111111111112
40 4.444444444444445
50 10.0
60 15.555555555555555
70 21.11111111111111
  • Hint: cent = (fahr - 32) / 9 * 5

Here is one possible Python program that solves this:

In [ ]:
fahr = 30
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 40
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 35
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 30
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 70
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 60
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
print(fahr, cent)
print(fahr, cent)
fahr = 70
cent = (fahr - 32) / 9 * 5
fahr = 70
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 70
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 70
cent = (fahr - 32) / 9 * 5
fahr = 60
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
fahr = 70
cent = (fahr - 32) / 9 * 5
print(fahr, cent)
30 -1.1111111111111112
40 4.444444444444445
35 1.6666666666666665
30 -1.1111111111111112
70 21.11111111111111
60 15.555555555555555
60 15.555555555555555
70 21.11111111111111

Why would copying code to do the same/similar thing multiple times in a row be a ...

  1. Good (or useful) thing?
  2. Bad (or difficulty-inducing) thing?
In [ ]:
for fahr in range (30, 71, 10):
    cent = (fahr - 32) / 9 * 5
    print(fahr, cent)

Copy and Paste Problems¶

  • Error prone
    • Copy-pasting in the wrong place
    • Changing the wrong values
    • Re-typing rather than copy/paste, causing typos
  • Can take a long time (luckily this list only had 5 values in it!)
  • What if …
    • Modifications: I decide I want to change the output format?
    • Bugs: I made a mistake in the formula?
    • Readability: Is it obvious to a human reader that all 5 chunks of code are identical without looking carefully?

For each fahr, do "this"¶

  • Where "this" is:
cent = (fahr - 32) / 9.0 * 5
print(fahr, cent)
  • Would be nice if we could write "this" just once
    • Easier to modify
    • Easier to fix bugs
    • Easier for a human to read

A for loop¶

for fahr in [30, 40, 50, 60, 70]:
    cent = (fahr - 32) / 9 * 5
    print(fahr, cent)
  • for: Starts with the word for
  • fahr: loop/iteration variable
  • [30, 40, 50, 60, 70]: A list (but can be any sequence expression).
    • We will cover more about lists and other sequences later!
  • Colon is required
  • Loop body is indented (just like if statements!)
    • Indentation is significant!

This code executes the body 5 times:

  • once with fahr = 30
  • once with fahr = 40
  • ...

Loop Examples¶

Prints the value of a sequence

In [ ]:
for num in [2, 4, 6]:
    print(num)

Does not use values of a sequence

In [ ]:
for iteration_Variable___ in [1, 2, 3]:
    print("Hi there!")

Sequence is a string and prints each value (char)

In [2]:
"happy" + " birthday"
Out[2]:
'happy birthday'
In [ ]:
x = 42
y = 42
this_is_athing = 42
In [ ]:
for char in "happy":
    print(char)
h
a
p
p
y
In [ ]:
for character in ["happy", "birthday", "I", "have", "a", "present"]:
    print(character)
happy
birthday
I
have
a
present
In [6]:
word = "happy"
for char in word:
    print(char)
h
a
p
p
y
In [8]:
for word in ["happy", "birthday", "I", "have", "a", "present"]:
    print(word)
    for char in word:
        print(char)
happy
h
a
p
p
y
birthday
b
i
r
t
h
d
a
y
I
I
have
h
a
v
e
a
a
present
p
r
e
s
e
n
t

How a loop is executed: Transformation vs Direct Approach¶

Idea: convert a for loop into something we know how to execute

Transformation Approach

  1. Evaluate the sequence expression
  2. Write an assignment to the loop variable, for each sequence element
  3. Write a copy of the loop after each assignment
  4. Execute the resulting statements

Direct Approach

  1. Evaluate the sequence expression
  2. While there are sequence elements left:
    • Assign the loop variable to the next remaining sequence element
    • Run the loop body
In [ ]:
for i in [1, 2, 3]:
    print(i)
In [ ]:
i = 1
print(i)
i = 2
print(i)
i = 3
print(i)
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
# Transformation Approach

i = 1
print(i)
i = 4
print(i)
i = 9
print(i)

# Direct Approach

for i in [1, 4, 9]:
    print(i)

The body can be multiple statements¶

Execute the whole body, then execute whole body again, etc.

In [ ]:
for i in [3, 4, 5]:
    print("Start body")
    print(i)
    print(i * i)

NOT:

Start body
Start body
Start body
3
4
5
9
16
25

Indentation is significant¶

  • Every statement in the body must have exactly the same indentation
  • That's how Python knows where the body ends
In [ ]:
for i in [3, 4, 5]:
    print("Start body")
    print(i)
    print(i * i)
  • Compare the results of these loops:
In [9]:
for f in [30, 40, 50, 60, 70]:
    print(f, (f - 32) / 9.0 * 5)
print("All done")
30 -1.1111111111111112
40 4.444444444444445
50 10.0
60 15.555555555555555
70 21.11111111111111
All done
In [10]:
for f in [30, 40, 50, 60, 70]:
    print(f, (f - 32) / 9.0 * 5)
    print("All done")
30 -1.1111111111111112
All done
40 4.444444444444445
All done
50 10.0
All done
60 15.555555555555555
All done
70 21.11111111111111
All done
In [12]:
print("1 / 2")
1 / 2
In [13]:
print(1 / 2)
0.5

The range function¶

A typical for loop does not use an explicit list:

for i in range(5):
  ... body ...

range(5): cycles through [0, 1, 2, 3, 4]

  • 5 is the upper limit (exclusive)

range(1, 5): cycles through [1, 2, 3, 4]

  • 1 is the lower limit (inclusive)

range(1, 10, 2): cycles through [1, 3, 5, 7, 9]

  • 2 is the step (distance between elements)

Some Loops¶

In [ ]:
# Sum of a list of values, what values?
result = 0
for element in range(5):
  result = result + element
print(f"The sum is: {result}")
In [ ]:
# Sum of a list of values, what values?
result = 0
for element in range(5, 1, -1):
  result = result + element
print(f"The sum is: {result}")
In [ ]:
# Sum of a list of values, what values?
result = 0
for element in range(0, 8, 2):
  result = result + element
print(f"The sum is: {result}")
In [ ]:
# Sum of a list of values, what values?
result = 0
size = 5
for element in range(size):
  result = result + element
print("When size = " + str(size) + " result is " + str(result))

How to process a list: One element at a time¶

  • A common pattern when processing a list:

result = initial_value for element in list: result = updated result use result

# Sum of a list
result = 0
for element in mylist:
  result = result + element
print(result)
  • initial_value is a correct result for an empty list
  • As each element is processed, result is a correct result for a prefix of the list
  • When all elements have been processed, result is a correct result for the whole list

Examples of list processing¶

  • Product of a list:
In [ ]:
mylist = [1, 2, 3, 4, 5]
result = 1
for element in mylist:
  result = result * element
print(result)
  • Maximum of a list:
In [ ]:
mylist = [5, 1, 4, 2, 3]
curr_max = mylist[0]
for element in mylist:
    curr_max = max(curr_max, element)
print(curr_max)

Approximate the value 3 by

$1 + 2/3 + 4/9 + 8/27 + 16/81 + … =\\ (2/3)^0 + (2/3)^1 + (2/3)^2 + (2/3)^3 + … + (2/3)^{10}$

In [ ]:
result = 0
for element in range(11):
  result = result + (2.0 / 3.0) ** element
print(result)