= 0
thesum for i in [3,2,1,9.9]:
+= i thesum
7 Loops
Loops allow programs to rerun the same block of code multiple times. This might seem like a funny thing to want to do but it turns out that there are many important tasks that are repetitive in nature (perhaps with small changes for each successive repetition). A loop provides a succinct and efficient way to perform tasks of this nature.
7.1 for
loops
The for
loop is probably the most common loop you will encounter and is a good choice when you know beforehand exactly what things you want to loop over. Here is an example of a for
loop that is used to add up the elements of a list.
This would be equivalent to the following code:
= 0
thesum
= thesum + 3
thesum = thesum + 2
thesum = thesum + 1
thesum = thesum + 9.9 thesum
which isn’t that much longer than using a loop. However, as the list gets longer and/or the mathematical operations being performed get more complex the second method would get unreasonably long.
The correct language is to say that we are iterating over the list [3,2,1,9.9]
. This means that the loop variable (i
in this case but you can choose it to be whatever you want) gets assigned the values of the list elements, one by one, until it reaches the end of the list. You can use for
loops to iterate over any multi-element object like lists or tuples. Python uses indentation to indicate where the loop ends. In this case there was only one statement inside to loop, but if you wanted more than one each line should be indented.
To Do:
- Add a
thesum
.- Predict what the output will be and then run the code and verify that you were correct.
- Now change the loop variable to be named
physics
and verify that the loop still works as expected.
You can iterate over range
objects and strings using for
loops.
for i in ['Physics', 'is','so','fun']: # Iterate over a list of strings
print(i)
Physics
is
so
fun
for i in range(5,50,3): #Generates a list from 5 -> 50 with a step size of 3
print(i)
5
8
11
14
17
20
23
26
29
32
35
38
41
44
47
These examples are so simple that you might wonder when a loop might actually be useful to you. Let’s see if we can build a loop to calculate the following sum
\[ \sum_{n=1}^{1000} {1\over n^2} \tag{7.1}\]
= 0
theSum for n in range(1,1000):
= theSum + 1/n**2
theSum print(theSum)
1.6439335666815615
Here, n
is being assigned the values 1,2,3,4....1000
, one by one, until it gets all the way to 1000. Each time through the loop, n
is different and the expression 1/n**2
evaluates to a new value. The variable theSum
is updated each time through to be the running total of all calculations performed thus far. Here’s another example of a loop used to calculate the value of \(20!\):
= 1
theProduct for n in range(1,21):
= theProduct * n #Multiply theProduct by n
theProduct print(theProduct)
2432902008176640000
Remember that the range function creates a list starting at \(1\), going up to \(21\) but not including it. The math library has a function called factorial
that does the same thing. Let’s use it to check our answer:
from math import factorial
20) factorial(
2432902008176640000
7.1.1 Boolean Logic Inside Loops
Often when using loops, we only want a block of code to execute when some condition is satisfied. We can use boolean logic inside of the loop to accomplish this. For example, let’s write a loop to compute the following sum:
\[ \sum_{{n\over 5} \in \text{ Int and } {n\over 3} \in \text{ Int}} {1\over n^2} \]
which is similar to the one we did above, but this time we only want to include terms where \(n\) is a perfect multiple of both 5 and 3. To check to see if n
is a perfect multiple of a number we can calculate the modulo (remainder after division) using the %
operator and check that it is equal to zero.
= 0
theSum for n in range(1,1000):
if n % 5 == 0 and n % 3 == 0:
= theSum + 1/n**2
theSum print(theSum)
0.007243985583159138
To Do:
Perform the following modifications to the loop above.
- Increase the upper bound of the sum to go up to and include \(5000\).
- Only include the terms where
n
is a multiple of 5 and 3 or is a multiple of 7.- Replace the statement that updates
theSum
to its shorthand version.
7.1.2 Zipping and Enumerating
There are times when it is necessary to iterate over two lists simultaneously. For example, let us say that we have a list of atomic numbers (AN
) and a list of approximate atomic masses (mass
) of the most abundant isotopes for the first six elements on the periodic table.
AN = [1,2,3,4,5,6]
mass = [1,4,7,9,11,12]
If we want to calculate the number of neutrons in each isotope, we need to subtract each atomic number from the atomic mass. To accomplish this, it would be nice to iterate over both lists simultaneously
7.1.2.1 Zipping
The simplest way to iterate over two lists simultaneously is to combine both lists into a single, iterable object and iterate over it once. The zip
function does just that by merging two lists or tuples into a nested list
= [1,2,3,4,5,6]
AN = [1,4,7,9,11,12]
mass
= zip(AN,mass)
zipped
for pair in zipped:
print(pair[1] - pair[0])
0
2
4
5
6
6
The zip objects are “single use” so you can’t reuse zipped
in a later loop. If the two lists being zipped are not the same length, zip
stops zipping when it reaches the end of the shorter list.
To Do:
- Print the variable
zipped
and inspect closely. Was the output what you expected?
- Now do
print(tuple(zipped))
and inspect closely. Draw a conclusion.- Add a few more entries to the list named
AN
, but don’t add the corresponding entries to the other list. Now the lists being zipped aren’t the same length. Inspect the output of the print statement to determine whatzip
does in this scenario.
7.1.2.2 Enumeration
A close relative to zip
is enumerate
which zips a list to the index value for that list (read that last statement again). It also returns a “single use” object that can be iterated over.
= [1,2,3,4,5,6]
AN = [1,4,7,9,11,12]
mass
= enumerate(mass)
enum
for idx,val in enum:
print(val - AN[idx])
0
2
4
5
6
6
To Do:
- Repeat the previous To-Dos for the cell above.
7.1.3 List Comprehension
It is fairly common to use a for
loop to populate a list with a sequence of numbers.
= []
myList
for i in range(10):
**2)
myList.append(i
print(myList)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
This entire process can be compressed down into a single line by expressing the for
loop in square brackets. This is known as list comprehension. The code below will generate the list as above.
= [i**2 for i in range(10)]
myList print(myList)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
List comprehension can take a little time to get used to but it is well worth it. It saves both time and space and makes code less cluttered. You can even add boolean expressions to your conditionals for further control of the final result.
= [i**2 for i in range(10) if i %2 == 0] # Include only the evens.
myList print(myList)
[0, 4, 16, 36, 64]
To Do:
Think of your favorite mathematical function and modify the code above to generate a few samples from it.
7.2 while
Loops
Logic can be combined with loops using something called a while
loop. A while
loop is a good choice when you don’t know beforehand exactly how many iterations of the loop will be executed but rather want the loop to continue to execute until some condition is met. As an example, notice that in Equation 7.1, the terms in the sum get progressively smaller as \(n\) gets bigger. It doesn’t make sense to continue adding to the sum once the terms get very small. Let’s compute this sum by looping until the fraction \({1 \over n^2}\) become smaller than \(1 \times 10^{-2}\).
= 1 # Load the first term in the sum
term = term # Initialize the sum
s = 1 # Set a counter
n while term > 1e-2: # Loop while term is bigger than 1e-2
= n + 1 #Add 1 to n so that it will count: 2,3,4,5
n = 1./n**2 # Calculate the next term to add
term = s + term # Add 1/n^2 to the running total s
This loop will continue to execute until term<1e-2
. Note that unlike the for
loop, here you have to do your own counting if you need to know how many iterations have been performed. Be careful about what value n
starts at and when it is incremented (n = n + 1
). Also notice that term
must be assigned prior to the start of the loop. If it wasn’t the loop’s first logical test would fail and the loop wouldn’t execute at all.
To Do:
- Decrease the threshold on the termination condition and observe any changes in the final result and how many more iterations are performed.
- After toying around with it for a while pick a termination condition that you feel will produce a result that is accurate.
while
loops should be used with caution because you can easily write a faulty termination condition and inadvertently write a loop that runs forever. This happens because your termination condition was never met. An example of this is given below.
Warning: Do not execute the code block below!!
= 0
x
while x != 10:
= x + 3
x print("Done")
The loop above is intended to end after a few iterations when the value of x is equal to 10. However, closer inspection reveals that the value of x will never be equal to 10. After the first iteration x is equal to 3, then 6,9,12,15 and so on… but never 10. This loop will run forever because the termination condition is never met (x != 10
never produces a False
)!! If you choose to use a while
loop, triple check your termination condition to make sure you haven’t made a mental error. Avoiding the use of !=
or ==
in your termination condition will help too. Use <=
or >=
instead.
To Do:
- Modify the termination condition in the loop above so that it terminates when
x
gets larger than 15.- Run the code and verify that you did it correct.
7.3 continue
, break
, and pass
Commands
The continue
, break
, and pass
commands are used to control the flow of code execution in loops. Here is a description of their usage:
Operator | Description |
---|---|
break |
Exits a for /while loop. |
continue |
Skips the remaining loop block and begins the next iteration. |
pass |
No action; code contiues on |
The break
statement is useful when you want to completely stop a loop early. Here is our sum loop rewritten with a break
statement added to stop the loop after 1000 iterations.
= 1 # Load the first term in the sum
term = term # Initialize the sum
s = 1 # Set a counter
n while term > 1e-10: # Loop while term is bigger than 1e-10
+= 1 #Add 1 to n so that it will count: 2,3,4,5
n = 1./n**2 # Calculate the next term to add
term += term # Add 1/n^2 to the running total
s if n > 1000:
print('This is taking too long. I''m outta here...')
break
This is taking too long. Im outta here...
The continue
statement is similar to break
except that instead of stopping the loop, it only stops the current iteration of the loop. All code below the continue
statement will be skipped and the next iteration will begin. For example, if you wanted to do the sum from equation ?? but only include those terms for which n is a multiple of 3, it could be done like this:
= 1 # Load the first term in the sum
term = term # Initialize the sum
s = 1 # Set a counter
n while term > 1e-10: # Loop while term is bigger than 1e-10
+= 1 #Add 1 to n so that it will count: 2,3,4,5
n if n % 3 != 0:
continue
= 1./n**2 # Calculate the next term to add
term += term # Add 1/n^2 to the running total s
Now, when the value of n
is not a multiple of 3, the sum will not be updated and the associated terms are effectively skipped.
Finally, the pass
statement does nothing. Seriously!! It is merely a place holder for code that has not bee written yet. Usually, you’ll use the pass
statement to run and test code without errors due to missing code.
7.4 Flash Cards
- Explain the basic structure and key elements of a
for
loop. - Explain the basic structure and key elements of a
while
loop. - What does the
break
statement do? - What does the
continue
statement do? - What does the
pass
statement do? - What does the
zip
function do? Give an example. - What does the
enumerate
function do? Give an example. - What is list comprehension? Give an example.
- Where is the account of Jesus walking on the water?
7.5 Exercises
- Use a loop to construct a list containing the first 10 fibonacci numbers that are multiples of \(5\). (The modulo operator (
%
) is a good and efficient way to see if a number is a multiple of another.)
Hint/Answer: The 10th fibonacci number that is a multiple of 5 is: 12,586,269,025
# Python code here.
Summations appear often in science and mathematics. One such summation is called the Riemann Zeta function and is given by \[ \zeta(n) = \sum_{k=1}^\infty {1\over k^n} = {1\over 1^n} + {1\over 2^n} + {1\over 3^n} + \dots\]
- Use a
for
loop to evaluate \(\zeta(2)\) and \(\zeta(4)\) and verify that \(\zeta(2) = {\pi^2 \over 6}\) and \(\zeta(4) = {\pi^4 \over 90}\). This summation is called an infinite sum and we surely don’t want our loop to continue forever!! Instead, an infinite sum like this one can be approximated with afor
loop with a large number of iterations. To determine if you have included enough terms, increase the number of terms steadily and watch for the final result to stop changing appreciably. - Now repeat part 1 using list comprehension and the
sum
function? - Repeat the exercise one final time using a
while
loop. Write thewhile
loop so that it stops iterating when the value of \({1\over k^n}\) gets smaller than \(1 \times 10^{-6}\).
- Use a
#Python code here
(Prime numbers) A prime number is a number that is not the product of two smaller numbers except \(1\). (i.e it is only evenly divisible by itself and \(1\)) To determine whether a number (\(n\)) is prime, check to see if the number is divisible by any integer starting at \(2\) and ending at \(\sqrt{n}\) (rounded up). If the number is divisible by even one of these integers, you know the number isn’t prime.
- Write a
for
loop that determines whether a specified number is prime or not. Try your loop out on the following numbers: \(75\), \(71\), and \(91\). - Repeat step 1 using a
while
loop. Be sure to include a fail-safe with abreak
statement to avoid infinite loops. - Now enclose your loop from either step 1 or step 2 inside another
for
loop to find all of the prime numbers that are less than \(500\). Put all of these numbers in a list. Hint: You should find that there are \(95\) prime numbers less than \(500\) - Finally, enclose your loop from either step 1 or step 2 inside another
while
loop to find the first \(500\) prime numbers. As always withwhile
loops be sure to include a fail-safe with abreak
statement to avoid infinite loops. Put all of these numbers into a list and verify that the list contains \(500\) numbers. Hint: The 500th prime number is \(3571\)
- Write a
# Python code here
The greatest common divisor (GCD) of two numbers is the greatest positive integer that divides each of the numbers. For example, the GCD of \(30\) and \(20\) is \(10\) (i.e. There is no number greater than \(10\) that divides both \(30\) and \(20\)). One algorithm for finding this number is called Euclid’s algorithm. The process for Euclid’s algorithm is as follows: (as long as both numbers are not negative.)
- Find the remainder of dividing the larger number by the smaller number.
- Replace the larger number with the number found in step 1.
- Repeat this process until one of the numbers is zero. At this point, the other number is the GCD.
- Use a
while
loop to find the GCD of \(105\) and \(252\). You may want to find the GCD of smaller numbers first to verify that your code is working. - The least common multiple (LCM) of two numbers is the smallest number that two or more numbers can divide evenly. For example, the LCM of \(6\) and \(4\) is \(12\) (i.e. There is no number smaller than \(12\) that is also a multiple of both \(6\) and \(4\)). The LCM can be found from the GCD using the following expression: \(LCM(a,b) = {a \times b\over GCD(a,b)}\). Calculate the LCM of \(105\) and \(252\).
- If \(GCD(a,b) = 1\) then the numbers are considered co-prime. Can you find a co-prime pair?
#Code here.
Another interesting summation is given by: \[ f(n) = \sum_{k=0}^\infty (-1)^k {1\over n^k} = {1\over n^0} - {1\over n^1} + {1\over n^2} - {1\over n^3} + {1\over n^4} - \dots\] This sum converges (approaches) the value \({n \over n + 1}\) only if \(n > 1\).
- Use a
for
loop to evaluate \(f(2)\) and \(f(4)\) and verify that \(f(2) = {2 \over 2 + 1} = {2\over 3}\) and \(f(4) = {4 \over 4 + 1} = {4\over 5}\). This summation is called an infinite sum and we surely don’t want our loop to continue forever!! Instead, an infinite sum like this one can be approximated with afor
loop with a large number of iterations. To determine if you have included enough terms, increase the number of terms steadily and watch for the final result to stop changing appreciably. - Now repeat part 1 using list comprehension and the
sum
function? - Repeat the exercise one final time using a
while
loop. Write thewhile
loop so that it stops iterating when the value of \({1\over n^k}\) gets smaller than \(1 \times 10^{-6}\). - Now investigate what happens when \(n = 0.5\). Do this by running your
for
loop from part 1 for more and more iterations and observing whether the sum approach one value (converges) or increases without bound (diverges).
- Use a
In the cell below you will find a dictionary containing the mass(in kg) and diameter of the planets in our solar system. Use a loop to iterate over this dictionary and calculate the acceleration due to gravity at the surface of the planet. \[ g = {G M \over R^2}\]. (\(G = 6.67 \times 10^{-11}\)) Then add this value to the list for each planet. Print the dictionary when you are done to verify that each dictionary entry is a list with three elements.
= {"Mercury": [0.33e24,4.879e6],"Venus":[4.87e24,1.2104e7],"Earth":[5.97e24,1.2756e7],"Mars":[0.642e24,6.792e6],"Jupiter":[1.898e27,1.42984e8],"Saturn":[5.68e26,1.20536e8],"Uranus":[8.68e25,5.1118e7],"Neptune":[1.02e26,4.9528e7],"Pluto":[0.013e24,2.376e7]} planetData
(Extra Credit) A transcendental equation is one that cannot be solved analytically (with pencil and paper). Try solving the following equation for x to see what I mean: \[ {\cos x \over x} = 1\] One numerical method for solving an equation like this involves first rearranging it to look like this: \[ x = \cos x\] and then using a loop to repeatedly evaluating the right hand side, using the result of the previous evaluation as the input, until \(x\) and \(\cos(x)\) are essentially equal (to within \(1 \times 10^{-3}\) is sufficient). 1 The first few iterations of this process might look something like this: \[(x_\text{old})_1 = 2 \text{ (starting guess)}\] \[(x_\text{new})_1 = \cos((x_\text{old})_1)\] \[(x_\text{old})_2 = (x_\text{new})_1\] \[(x_\text{new})_2 = \cos((x_\text{old})_2)\] \[(x_\text{old})_3 = (x_\text{new})_2\] \[(x_\text{new})_3 = \cos((x_\text{old})_3)\]
1 This is called successive relaxation.
- Use a
while
loop to solve this equation and report the correct value for x.
- Plug the answer back into the equation to verify that it indeed does satisfy the equation.
- Report how many iterations it took to solve the problem.
- Decrease the value in the termination condition and observe how the number of iterations and the accuracy of the answer change.
= 2 # starting guess x