PHOT 110: Introduction to programming

LECTURE 03

Michaël Barbier, Spring semester (2023-2024)

Control flow: conditional branching and loops

Control flow: conditional branching and loops

  • Branching if/else statements
  • The while loop
  • Lists of objects
  • The for loop: iterating over a list

Conditional branching: if/elif/else

Conditional branching

  • Run code-blocks according to a condition
    • An if code-block is executed when the condition is True
    • An else code-block is executed when the condition is False
if <condition>:
    <statement>
    ...
if <condition>:
    <statement>
    ...
else <condition>:
    <statement>
    ...

Conditional branching

  • elif keyword acts as a else if
  • multiple elif statements can follow an if, with an optional else
if <condition>:
    <statement>
    ...
elif <condition>:
    <statement>
    ...
elif <condition>:
    <statement>
    ...
else <condition>:
    <statement>
    ...
if <condition>:
    <statement>
    ...
elif <condition>:
    <statement>
    ...
elif <condition>:
    <statement>
    ...

Conditional branching

  • Run code-blocks according to a condition
    • An if code-block is executed when the condition is True
age = 46
if age >= 16:
  print("You can drive a tractor")  # if code-block
You can drive a tractor

Conditional branching

  • Run code-blocks according to a condition
    • if code-block is executed when the condition is True
  • The indented code-block can contain multiple statements
speed_limit = 120
speed = 137
if speed > speed_limit:
  speed_diff = speed - speed_limit
  print(f"You drive {speed_diff} km/h too fast")
You drive 17 km/h too fast

Conditional branching

  • Run code-blocks according to a condition
    • if code-block is executed when the condition is True
    • else code-block is executed when the condition is False
age = 11
if age > 18:
  print("You can drive a car")
else:
  print("You should take the bus")
You should take the bus

Conditional branching

  • Run code-blocks according to a condition
    • if code-block is executed when the condition is True
    • else code-block is executed when the condition is False
    • elif keyword acts as a else if
age = 17
if age > 18:
  print("You can drive a car")
elif age > 16:
  print("You can drive a tractor")
else:
  print("You can ride a bicycle")
You can drive a tractor

Conditional branching

  • Run code-blocks according to a condition
    • if code-block is executed when the condition is True
  • The indented code-block can contain multiple statements
  • indentation is the same within a code-block
age = 19
if age > 18:
    print("You can drive a car")    # This line is indented differently
  print("You can drive a bicycle")
  print("You can drive a tractor")
IndentationError: unindent does not match any outer indentation level (<string>, line 4)

While Loop

The while loop

  • Repeats code-block until the condition is False

  • A while loop is used when:

    • we don’t know how many iterations we need, and
    • we have a stopping criterium/condition
    while <condition>:
      <statement>
      <statement>
      <statement>
      ...
      <statement>

The while loop

  • Repeats code-block until the condition is False

  • A while loop is used when:

    • we don’t know how many iterations we need, and
    • we have a stopping criterium/condition
    t = 0; t_max = 10
    while t < t_max:
      t = t + 3.86
      print(f"The elapsed time is: {t:5.3} s")
    print("End of the program")
    The elapsed time is:  3.86 s
    The elapsed time is:  7.72 s
    The elapsed time is:  11.6 s
    End of the program

The while loop

  • Repeats code-block until the condition is False

  • Can get in an infinite loop !

    • Stop the program with the stop button, in a terminal press key combination Ctrl + c
    • Adapt the stopping criterium/condition
    n = 0
    while n > -100:
    n = n + 1
    print(f"The current number is: {n}")

Python lists

Lists of objects

  • A list can contain several objects
  • The object types can be different
  • Lists are also objects
# A list with mixed object types
my_list_of_objects = ["It's Monday", False, 34, 23.4]

# Lists can be elements of a list
a_list_with_a_list = [5, 10.5, ["green", "red"], True]
print(a_list_with_a_list)
[5, 10.5, ['green', 'red'], True]

Lists of objects

  • Length of the list is the number of elements applying the len() function: len(a_list)
  • The object types can be different
  • Lists are also objects
# A list with mixed object types
my_list_of_objects = ["It's Monday", False, 34, 23.4]

# Lists can be elements of a list
a_list_with_a_list = [5, 10.5, ["green", "red"], True]
print(a_list_with_a_list)
[5, 10.5, ['green', 'red'], True]

Appending an element to a list

  • Append an element to the end of a list
  • Length (number of elements) of the list increases with one
# Printing the first and then the second element
a_list = ["First", False, 34, 23.4]
print(a_list)
print(f"The length of the list = {len(a_list)}")
a_list.append("extra_element")
print(a_list)
print(f"The length of the adapted list = {len(a_list)}")
['First', False, 34, 23.4]
The length of the list = 4
['First', False, 34, 23.4, 'extra_element']
The length of the adapted list = 5

More methods of list

a_list = ["First", False, 34, 5, 34]  # Define the list
a_list.remove(34)                     # Remove first 34
a_list.insert(3, "inserted_string")   # Insert str
print(a_list)                         # Print the list
['First', False, 5, 'inserted_string', 34]

Selecting elements in a list

  • Select an element of a list by its index
  • syntax for indexing: a_list[element_index]
  • index is zero-based
  • negative index starts from the end of the list
# Printing the first and then the second element
a_list = ["First", False, 34, 23.4]
print(a_list[0])
print(a_list[1])
First
False

Selecting elements in a list

  • Select an element of a list by its index
  • syntax for indexing: a_list[element_index]
  • index is zero-based
  • negative index starts from the end of the list
# Using negative indexing
a_list = ["First", False, 34, 23.4]
print(a_list[-1])
23.4

Slicing a list

  • Selecting multiple elements is called slicing
  • syntax for slicing: a_list[start:stop_exclusive]
# A list with mixed object types
a_list = [23, 45, 65, 78, 92, 100, 102, 105 ]
print(a_list[2:5])
[65, 78, 92]

Slicing a list

  • Selecting multiple elements is called slicing
  • syntax for slicing: a_list[start:stop_exclusive]
# An empty start_index starts from the first index
a_list = [23, 45, 65, 78, 92, 100, 102, 105 ]
print(a_list[:5])
[23, 45, 65, 78, 92]
# An empty end_index end at the last index
a_list = [23, 45, 65, 78, 92, 100, 102, 105 ]
print(a_list[3:])
[78, 92, 100, 102, 105]

Slicing a list

  • Selecting multiple elements is called slicing
  • syntax for slicing: a_list[start:stop_exclusive]
  • Additional step parameter: a_list[start:stop_exclusive:step]
# Take every second element by stepping
a_list = [23, 45, 65, 78, 92, 100, 102, 105 ]
print(a_list[1::2])
[45, 78, 100, 105]

The for loop

The for loop

  • To iterate: to repeat a process
  • A for loop can be used when:
    • the number of iterations is known, or
    • we iterate over a list of elements
for <element> in <list>:
    <statement>
    <statement>
    ...
    <statement>

The for loop

  • To iterate: to repeat a process
  • A for loop can be used when:
    • the number of iterations is known, or
    • we iterate over a list of elements
# Print all elements of a list
days = ["Mon", "Tue", "Wed", "Thu", "Fri"]
for el in days:
  print(el)
Mon
Tue
Wed
Thu
Fri

Intermezzo: using range()

# A list with mixed object types
a_range = range(1, 10, 2)  # Construct a range
print(a_range)             # Lazy evaluated
print(list(a_range))       # Converted to a list
range(1, 10, 2)
[1, 3, 5, 7, 9]

The for loop

  • To iterate: to repeat a process
  • A for loop can be used when:
    • the number of iterations is known, or
    • we iterate over a list of elements
# Use the range function to get a sequence of numbers
for i in range(1,10,2):
  print(i)
1
3
5
7
9

The for loop

  • To iterate: to repeat a process
  • A for loop can be used when:
    • the number of iterations is known, or
    • we iterate over a list of elements
# Use the range function to get indices
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
for i in range(0,len(days),2):
  print(days[i])
Mon
Wed
Fri
Sun

Example scientific algorithm

Numerical approx. of the trajectory of a ball

  • Gravitation: \(g=9.81\) m/s\(^2\)
  • Air resistance: ignore for a slow heavy ball
  • horizontal velocity is constant

Trajectory of a ball

# Load library for sine and cosine
import math

# Algorithm parameters in MKS units
v0 = 6
angle_in_degrees = 37
g = 9.81
x = 0; y = 1.20; t = 0

# Calculate initial velocity in x 
#     and y directions
angle = angle_in_degrees * math.pi/180
vx = v0 * math.cos(angle)
vy = v0 * math.sin(angle)

# Initiate values at time t = 0
x_values = list([x])
y_values = list([y])
t_values = list([t])

dt = 0.1
while (y >= 0) and (t < 10):
  # update velocities (vx, vy), coords
  #     (x, y), and time t
  vy = vy - g*dt
  y = y + vy*dt
  x = x + vx*dt
  t = t + dt
  x_values.append(x)
  y_values.append(y)
  t_values.append(t)
  print(f't = {t:.2f}: ({x:.2f},{y:.2f})')

Trajectory of a ball

t = 0.10: (0.48,1.46)
t = 0.20: (0.96,1.63)
t = 0.30: (1.44,1.69)
t = 0.40: (1.92,1.66)
t = 0.50: (2.40,1.53)
t = 0.60: (2.88,1.31)
t = 0.70: (3.35,0.98)
t = 0.80: (3.83,0.56)
t = 0.90: (4.31,0.04)
t = 1.00: (4.79,-0.58)

Numerical approximation errors

Comparison with exact trajectory obtained before

Summary

  • Control flow exists of
    • Branching if/else
    • while/for loops
  • Allows implementing complex algorithms
  • Lists are versatile data structures
  • The for loop: iterating over list elements
  • More complex scientific algorithms:
    • Iterative methods
    • Stopping criteria