Computational Methods in Physics ASU Physics PHY 494

04 Python II — Flow control

We are continuing from the previous lesson in the "work directory" ~/PHY494/04_python. We will use ipython and your text editor.

Flow control

Flow control is essential for any programming language.

  • loops: for and while
  • conditionals: if ... elif ... else
  • exceptions: try ... except (will be discussed another time)

Loops

Computers are excellent at repeating instructions. Looping constructs are used to repeat a block of code for a fixed number of iterations or until a given condition is met.

The for loop

The for statement executes a code block (the "body" of the for-loop) once for each item in a sequence:

for VARIABLE in SEQUENCE:
    # for-block
    ...   
  • White-space indentation demarcates a block: Convention: Use 4 spaces for each indentation level (not TABS)
  • VARIABLE is set to each item of SEQUENCE in turn. You can use VARIABLE in the loop body.
  • SEQUENCE can be a list, tuple, string, … any "iterable".

Example: Convert all the measured temperatures from Fahrenheit to Kelvin, using a for loop.

Create a python program temperatures.py

# temperature conversion

temperatures = [60.1, 78.3, 98.8, 97.1, 101.3, 110.0]
for theta in temperatures:
   T = (theta - 32) * (5/9) + 273.15
   print(T)
   
print("Conversion complete")

and run it1

python temperatures.py

to yield

288.76111111111106
298.8722222222222
310.26111111111106
309.31666666666666
311.65
316.4833333333333
Conversion complete
Activity: for loop
  1. create temperature.py as above and run it
  2. modify temperature.py so that the results are stored in a new list temp_Kelvin
Loops with range()

The range() "function" provides "standard" (as in e.g., C) for-loop behavior:

range(stop) iterates through 0, 1, 2, …, stop-1

for i in range(7):
    print(i)

and gives 0 1 ... 5 6 whereas range(start, stop, step) iterates through start, start+step, start+2*step, … with the last element less than stop:

for i in range(1, 7, 2):
    print(i)

yielding 1 3 5.

Activity: range()

Add code to temperatures.py (below) to print a table of the temperature in F and in K side by side by iterating through the lists temperatures and temp_Kelvin simultaneously.

Hints:

  • You can use len() and range()2
  • Assign individual values to variables T_K and theta_F and print each line with the format print("{0:6.1f} F {1:6.1f} K".format(theta_F, T_K)).
# temperature conversion

temperatures = [60.1, 78.3, 98.8, 97.1, 101.3, 110.0]
temp_Kelvin = []
for theta in temperatures:
   T = (theta - 32) * (5/9) + 273.15
   temp_Kelvin.append(T)

# show T in F and K side by side
# ...
List comprehensions (advanced)

We often have to generate a list from computed values as the example T above. Instead of starting with an empty list and appending values, we can also use a list comprehension: the following code does the same as the one above:

# temperature conversion: list comprehension

temperatures = [60.1, 78.3, 98.8, 97.1, 101.3, 110.0]
temp_Kelvin = [(theta - 32) * (5/9) + 273.15 for theta in temperatures]

We write a for loop inside the list brackets where the "body" of the loop consists of a single expression that typically uses the list variable. It results in concise code that also generally executes much faster.

Activity: Generate values from -10 to 10 in steps of 0.25

Perform this activity using pair programming3.

We often need a range of values at arbitrary step size, e.g., for plotting a function. The range() function only provides integer numbers. Find a way to generate a list of numbers from start=-10 to stop=10 (exclusive) with step=0.25, i.e., [-10., -9.75, -9.5, ..., 9.5, 9.75].

Put your code into file grid.py and store your list in the variable x_grid.

(You can use list comprehensions. Think about how to use range() and how to use the integers to generate the floating point numbers.)

The while loop

The while loop (see also the while loop in the Python Tutorial) iterates over a code block until an expression (the "condition") evaluates to False:

while condition:
   # while-block
   ...

The while loop may execute zero times if condition is immediately False. It may also run an infinite number of times when the condition is always True.

Example: The program countup.py will run until t has exceeded a preset value tmax:

# countup.py

tmax = 10.
t, dt = 0, 2.

while t <= tmax:
   print("time " + str(t))
   t += dt
print("Finished")
Activity: reading input

A common problem is to read multiple inputs from a user until a specific input signals the end of input. The while loop works well in this case:

# read data until empty input

data = []
x = input()
while x != "":
    data.append(x)
    x = input()
    
print("data = {}".format(numbers))

Write a program alternatesum.py that computes the "alternating sum"

\[A = \sum_{k=0}^{N-1} (-1)^k a_k\]

from user input of \(N\) numbers \(a_k, 0 \le k < N\). Your program should

  1. read numbers from input until an empty line is encountered;
  2. store the numbers in a list numbers;
  3. calculate; the "alternating sum" numbers[0] - numbers[1] + numbers[2] - numbers[3] + ... and store it in a variable asum. (You can also print asum.)
Example (optional): Fibonacci sequence

The program fibonacci.py will compute the Fibonacci series

\[F_n = F_{n-1} + F_{n-2} \quad\text{with}\ F_1 = F_2 = 1\]

up to Fmax:

# fibonacci.py

Fmax = 100
a, b = 0, 1

while b < Fmax:
   print(b, end=' ')
   a, b = b, a+b
print()

Before running fibonacci.py, let's try to anticipate what the code will do. We will then run the code. If we get the expected results then, great!, otherwise: try to figure out why.

Anticipating results and comparing to the run afterwards is the scientific method applied to programming. It is essential if you want to become a good programmer.

Conditionals

Any programming language needs to be able to make decisions. Python has the if statement.

Example: Consider an implementation of the Heaviside step function

\[\Theta(x) = \begin{cases} 0 & x < 0 \\ \frac{1}{2} & x = 0\\ 1 & x > 0 \end{cases}\]

as heaviside.py

# Heaviside step function

x = 3
theta = None
if x < 0:
   theta = 0.
elif x == 0:
   theta = 0.5
else:
   theta = 1.

print("Theta(" + str(x) + ") = " + str(theta))

Activity (optional): Step function

Run heaviside.py for various values of x (at least -3, 0, 3) and test the output against the mathematical definition.

Activity: Guessing game I

Write a program guessinggame.py that takes a single number guess as input and compares it to a preset integer number secret_number. Tell the player if their guess was "too low", "too high", or that they "guessed the number". You can start with the code below:

# guessinggame.py

secret_number = 42
guess = int(input("Guess the number: "))

# add more code here...

BONUS: If you want to enhance this code you can try to generate a random number using the random.randint() function. (You will learn more about importing modules and functions later in this lesson.)

import random

number = random.randint(1, 1000)  # secret integer number between 1 and 1000

Activity (optional): Guessing game II

Perform this activity using pair programming3.

Enhance the simple guessing game from the previous exercise so that the player can guess repeatedly. Count the number of guesses and print them once the player guesses correctly.

You can use the following incomplete code as a starting point:

# guess.py

import random

secret_number = random.randint(1, 1000)  # secret integer number between 1 and 1000

n_guesses = 0
guess = int(input("Guess the number between 1 and 1000: "))

# add code
   
print("Congratulations, you guessed the number", number, "in", n_guesses, "guesses")

break and continue

The break statement ends a for or while loop.

The following example reads data from input until the special word "STOP" is encountered:

data = []
while True:
    x = input()
    if x == "STOP":
        break
    data.append(x)

print(data)

The for loop can also have an else clause that is only executed when the loop exits normally (i.e., not via a break). We will use this feature when checking for convergence of algorithms, using a pattern similar to the following:

for step in range(maxiter):
   value, convergence_criterion = do_calculation()
   if abs(convergence_criterion) < tolerance:
      break   # converged, use value
else:
   print("Calculation did not converge after {} steps.".format(maxiter))

print(value)

The continue statement immediately starts the next loop iteration.

The following example only prints something every 10 steps:

for step in range(100):
    if step % 10 != 0:
       continue
    print("step = {}".format(step))

We can use it in parsing content to skip empty lines:

text = "On the first line my true love\n  \n  brought to me\n\n\nOne python snake\n  in a directory tree.\n"
print(text)
for line in text.split('\n'):
    line = line.strip()  # remove leading and trailing white space
    if not line:
       continue
    print("line: ", line)

Footnotes

  1. Remember, in ipython you can also run the program with %run temperatures.py

  2. If you already know how to solve the problem with len(), range(), and indexing, try to figure out how to do it more elegantly with the zip() function 

  3. We will try a software engineering technique called pair programming (borrowed from agile/extreme programming)

    Each of the two programmers takes on one of the following roles:

    • driver: has keyboard & types, runs the code
    • navigator reads code, provides directions, catches bugs

    Both constantly talk to each other: comment on what you're typing, comment on what is being typed. Roles are not static but are supposed to be switched frequently.

    1. Split into teams of 2. (Be nice. Introduce yourselves.)
    2. Sit next to each other at one desk.

      Share a Zoom Breakout room

    3. Flip a coin to decide who will start out as the navigator and who will be the driver.
    4. Decide whose laptop you are going to use.

      The driver will share their screen and type and run code.

    5. Switch roles every ~5 minutes

      Maintain roles for one exercise (or switch if feasible, e.g., if you can quickly exchange code via a remote repository)

     2