Chapter 5: Control Flow - Making Decisions in Code#

Control flow is how we make our programs smart enough to make decisions and respond to different conditions. Instead of running every line of code sequentially, control flow lets you:

  • Execute code only when certain conditions are met

  • Choose between different options

  • Repeat actions multiple times

  • Handle errors gracefully

Think of it like decision points in real life:

  • “If it’s raining, take an umbrella”

  • “While studying, take breaks every hour”

  • “For each problem, check your answer”

  • “Try to open the file, but if it doesn’t exist, create a new one”

In this chapter, we’ll cover the main control structures:

  1. if-else statements (making decisions)

  2. for loops (repeating with sequences)

  3. while loops (repeating with conditions)

  4. try-except (error handling)

5.1 If Statements - Making Decisions#

If statements are the foundation of decision-making in programming. They let your code choose what to do based on different conditions.

Basic syntax:

if condition:
    # Code to run if condition is True
    # Note the indentation (4 spaces)!

Key points:

  • The condition must evaluate to True or False

  • Python uses indentation (4 spaces) to define code blocks

  • All indented lines after the if belong to that if block

print("=== Example: Reactor Temperature Safety Check ===")
reactor_temp = 110  # degrees Celsius

if reactor_temp > 100:
    print("WARNING! Temperature exceeds safe limit!")

if reactor_temp < 80:
    print("Temperature below optimal range!")
=== Example: Reactor Temperature Safety Check ===
WARNING! Temperature exceeds safe limit!

5.1.1 If-Else Statements#

If-else statements let you specify what to do when the condition is False. This gives you two possible paths.

Syntax:

if condition:
    # Code if condition is True
else:
    # Code if condition is False

Key insight: Exactly one of the two blocks will always run - either the if block or the else block, never both.

# If-Else Examples
print("\n=== Example: pH Classification ===")
pH = 3.5
print(f"Solution pH: {pH}")

if pH < 7:
    print(f"pH {pH} is ACIDIC")
    print("Handle with acid-resistant equipment")
else:
    print(f"pH {pH} is BASIC/NEUTRAL")
    print("Standard equipment acceptable")
=== Example: pH Classification ===
Solution pH: 3.5
pH 3.5 is ACIDIC
Handle with acid-resistant equipment
pH = 3.5
if pH < 7:
    print("handle with acid-resistant equipment")

if pH >=7:
    print("Standard equipment acceptable")
handle with acid-resistant equipment

5.1.2 If-Elif-Else Statements#

If-elif-else (else-if) statements let you check multiple conditions in sequence. This is perfect when you have more than two possible outcomes.

Syntax:

if condition1:
    # Code if condition1 is True
elif condition2:
    # Code if condition1 is False and condition2 is True
elif condition3:
    # Code if previous conditions are False and condition3 is True
else:
    # Code if all conditions are False

Important: Python checks conditions in order and executes only the first True block, then skips the rest!

# If-Elif-Else Examples

print("=== Example: Reactor Safety Classification ===")
pressure = 12.5  # bar

print(f"Reactor pressure: {pressure} bar")

if pressure < 5:
    classification = "Low Pressure"
    safety_level = "Standard PPE required"
elif pressure < 10: # if pressure >= 5 and pressure < 10:
    classification = "Medium Pressure"
    safety_level = "Enhanced PPE and monitoring"
elif pressure < 15: # if pressure >= 10 and pressure < 15
    classification = "High Pressure"
    safety_level = "Specialized equipment and certification required"
else:
    classification = "CRITICAL PRESSURE"
    safety_level = "EMERGENCY PROTOCOLS - Immediate shutdown!"

print(f"Classification: {classification}")
print(f"Safety requirement: {safety_level}")
=== Example: Reactor Safety Classification ===
Reactor pressure: 12.5 bar
Classification: High Pressure
Safety requirement: Specialized equipment and certification required

5.2 For Loops - Repeating Actions with Sequences#

For loops let you repeat code for each item in a sequence (like a list, string, or range). They’re perfect when you know what you want to iterate over.

Basic syntax:

for item in sequence:
    # Code to repeat for each item

Common sequences:

  • Lists: [1, 2, 3, 4, 5]

  • Strings: "hello" (iterates over each character)

  • Ranges: range(5) creates numbers 0, 1, 2, 3, 4

numbers = [10, 20, 30]

for x in numbers:
    print(x)
10
20
30
for char in "CHME212":
    print(char)
C
H
M
E
2
1
2
for i in range(5):
    print(i)
0
1
2
3
4
# For loop visualization:
# Iteration 1:  [10, 20, 30] → x = 10
#                 ↑
# Iteration 2:  [10, 20, 30] → x = 20
#                     ↑
# Iteration 3:  [10, 20, 30] → x = 30
#                         ↑

Iteration

Sequence

Current element

1

[10, 20, 30] → 10

x = 10

2

[10, 20, 30] → 20

x = 20

3

[10, 20, 30] → 30

x = 30

for i in range(5):
    print(i)
0
1
2
3
4

range is a built-in Python function that generates a sequence of integers.
It starts from a given value (default is 0), stops before the end value,
and can optionally increment by a specified step size.

range is commonly used to control how many times a for loop runs.

print("=== Example 1: Analyzing Reactor Samples ===")
sample_concentrations = [2.5, 3.1, 2.8, 3.0, 2.9]  # mol/L

print("Analyzing concentration measurements:")
for concentration in sample_concentrations:
    print(f"  Sample: {concentration} mol/L")
    if concentration > 3.0:
        print(f" Above target concentration: {concentration} mol/L")
        
=== Example 1: Analyzing Reactor Samples ===
Analyzing concentration measurements:
  Sample: 2.5 mol/L
  Sample: 3.1 mol/L
 Above target concentration: 3.1 mol/L
  Sample: 2.8 mol/L
  Sample: 3.0 mol/L
  Sample: 2.9 mol/L
# Basic For Loop Examples



print("\n=== Example 2: Chemical Formula Analysis ===")
formula = "H2SO4"

print(f"Elements in {formula}:")
for char in formula:
    if char.isalpha():
        print(f"  Element: {char}")
    elif char.isdigit():
        print(f"    Subscript: {char}")

print("\n=== Example 3: Temperature Monitoring ===")
print("Hourly reactor temperature readings:")
for hour in range(1, 6):  # Hours 1-5
    temp = 85 + hour * 2  # Simulated temperature increase
    print(f"  Hour {hour}: {temp}°C")

print("\nCooldown sequence:")
for temp in range(100, 69, -10):  # 100, 90, 80, 70
    print(f"  {temp}°C...")
print("  Safe temperature reached ✓")

print("\n=== Example 4: Pressure-Volume Calculations ===")
print("Ideal gas: PV = nRT (at constant n, T)")
print("If pressure doubles, volume is halved:")
for P in range(1, 6):
    V = 10 / P  # Inverse relationship
    print(f"  P = {P} atm → V = {V:.2f} L")

print("\n=== Example 5: Converting Concentrations ===")
concentrations_molL = [0.5, 1.0, 1.5, 2.0, 2.5]  # mol/L
concentrations_gL = []  # g/L (for NaCl, MW = 58.44 g/mol)

MW_NaCl = 58.44  # g/mol

print("Converting NaCl concentrations from mol/L to g/L:")
for conc_mol in concentrations_molL:
    conc_g = conc_mol * MW_NaCl
    concentrations_gL.append(conc_g)
    print(f"  {conc_mol} mol/L = {conc_g:.1f} g/L")

print(f"\nOriginal (mol/L): {concentrations_molL}")
print(f"Converted (g/L): {[round(c, 1) for c in concentrations_gL]}")
=== Example 2: Chemical Formula Analysis ===
Elements in H2SO4:
  Element: H
    Subscript: 2
  Element: S
  Element: O
    Subscript: 4

=== Example 3: Temperature Monitoring ===
Hourly reactor temperature readings:
  Hour 1: 87°C
  Hour 2: 89°C
  Hour 3: 91°C
  Hour 4: 93°C
  Hour 5: 95°C

Cooldown sequence:
  100°C...
  90°C...
  80°C...
  70°C...
  Safe temperature reached ✓

=== Example 4: Pressure-Volume Calculations ===
Ideal gas: PV = nRT (at constant n, T)
If pressure doubles, volume is halved:
  P = 1 atm → V = 10.00 L
  P = 2 atm → V = 5.00 L
  P = 3 atm → V = 3.33 L
  P = 4 atm → V = 2.50 L
  P = 5 atm → V = 2.00 L

=== Example 5: Converting Concentrations ===
Converting NaCl concentrations from mol/L to g/L:
  0.5 mol/L = 29.2 g/L
  1.0 mol/L = 58.4 g/L
  1.5 mol/L = 87.7 g/L
  2.0 mol/L = 116.9 g/L
  2.5 mol/L = 146.1 g/L

Original (mol/L): [0.5, 1.0, 1.5, 2.0, 2.5]
Converted (g/L): [29.2, 58.4, 87.7, 116.9, 146.1]

5.2.1 Advanced For Loop Techniques#

Python provides several powerful tools that make looping more expressive, readable, and efficient.

enumerate() – Looping with Index and Value

When looping through a sequence, you often need both the index and the value. enumerate() provides both at the same time.

for index, value in enumerate(sequence):
    # use index and value
fruits = ["apple", "banana", "cherry", "date"]

print("\nWith enumerate (get position AND value):")
for index, value in enumerate(fruits):
    print(f"  Position {index}: {value}")
With enumerate (get position AND value):
  Position 0: apple
  Position 1: banana
  Position 2: cherry
  Position 3: date

zip() – Looping Over Multiple Sequences Together

zip() allows you to iterate over multiple sequences in parallel.

names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["New York", "London", "Tokyo"]

print("Combining three lists together:")
for name, age, city in zip(names, ages, cities):
    print(f"  {name} is {age} years old and lives in {city}")
Combining three lists together:
  Alice is 25 years old and lives in New York
  Bob is 30 years old and lives in London
  Charlie is 35 years old and lives in Tokyo
manual_zipped_list = [("Alice", 25, "New York"), ("Bob", 30, "London"), ("Charlie", 35, "Tokyo")]
for name, age, city in manual_zipped_list:
    print(f"  {name} is {age} years old and lives in {city}")
  Alice is 25 years old and lives in New York
  Bob is 30 years old and lives in London
  Charlie is 35 years old and lives in Tokyo
list(zip(names, ages, cities))
[('Alice', 25, 'New York'), ('Bob', 30, 'London'), ('Charlie', 35, 'Tokyo')]

List Comprehension – Compact Loop for Creating Lists

A list comprehension is a concise way to create a new list by looping and optionally applying a condition.

# conventional for loop
new_list = []
for item in sequence:
    new_list.append(item)

# list comprehension
new_list = [expression for item in sequence]
# Traditional way with loop
celsius_temps = [20, 25, 30, 35, 40]
fahrenheit_traditional = []

for temp_c in celsius_temps:
    temp_f = temp_c * 9/5 + 32
    fahrenheit_traditional.append(temp_f)
    
print(fahrenheit_traditional)


fahrenheit_traditional = [temp_c * 9/5 + 32 for temp_c in celsius_temps]
print(fahrenheit_traditional)
[68.0, 77.0, 86.0, 95.0, 104.0]
[68.0, 77.0, 86.0, 95.0, 104.0]

Nested Loops – Loops Inside Loops

A nested loop is a loop placed inside another loop. The inner loop runs completely for each iteration of the outer loop.

for i in sequence1:
    for j in sequence2:
        # code using i and j
for i in range(3): # 0, 1, 2
    for j in range(2): # 0, 1
        print(i, j)

# i=0 → j=0, j=1
# i=1 → j=0, j=1
# i=2 → j=0, j=1
0 0
0 1
1 0
1 1
2 0
2 1
print("=== Nested Loops ===")
print("A loop inside another loop\n")

print("Multiplication table (3x3):")
for i in range(1, 4):
    for j in range(1, 4):
  Cell In[17], line 6
    for j in range(1, 4):
                         ^
SyntaxError: incomplete input
print("\n=== Nested Loops ===")
print("Stoichiometry table for A + 2B → C:")
print("Moles A | Moles B | Moles C")
print("--------|---------|--------")
for moles_A in range(1, 4):
    for moles_B in range(2, 8, 2):
=== Nested Loops ===
Stoichiometry table for A + 2B → C:
Moles A | Moles B | Moles C
--------|---------|--------
  1     |    2    |   1
  2     |    4    |   2
  3     |    6    |   3

5.3 While Loops - Repeating Until a Condition Changes#

While loops repeat code as long as a condition remains True. They’re perfect when you don’t know exactly how many times you need to repeat something.

Basic syntax:

while condition:
    # Code to repeat
    # Make sure to eventually make condition False!

Key difference from for loops:

  • For loop: “Do this for each item” or “Do this N times”

  • While loop: “Keep doing this until something changes”

count = 0

while count < 5:
    print(count)
    count += 1 # count = count + 1
0
1
2
3
4

Use for loops when:#

  • You know exactly how many times you want to iterate

  • You are looping over a sequence or collection (list, string, range, tuple, dictionary)

  • You want a concise, readable loop

Examples:

Looping over a list:

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

Use while loops when:#

  • You do not know in advance how many times the loop will run

  • You want to repeat until a condition changes

  • Iteration depends on dynamic data or user input

Examples:

Repeat until a condition is met:

number = 0
while number < 10:
    number += 2
    print(number)
answer = ""
while answer.lower() != "yes":
    answer = input("Do you want to continue? ")

Quick Comparison: for vs while#

Feature

for

while

Iteration count

Known / fixed

Unknown / dynamic

Best for

Sequences (lists, strings, ranges)

Conditional repetition

Risk

Rare

Can create infinite loops if condition never changes

Example

for i in range(5):

while x < 10:

5.3.1 While Loop Best Practices and Common Patterns#

Infinite loop: An infinite loop occurs when the loop’s condition never becomes false, causing the loop to repeat forever. This can happen with both while and for loops (though it’s more common with while loops).

Infinite loops can freeze programs or consume resources, so it’s important to understand and avoid them.

print("=== ⚠️  DANGER: Infinite Loop (Don't run this!) ===")
print("# This would run forever:")
print("# count = 1")
print("# while count <= 5:")
print("#     print(count)")
print("#     # Forgot to increment count - INFINITE LOOP!")
print("# ")
print("# Always make sure your condition will eventually become False!")

Pattern 1: Counter-Based Loop

Purpose: Repeat an action a fixed number of times using a counter.

i = 1
while i <= 3:
    print(f"  Step {i}")
    i += 1  # Always update the counter!
  Step 1
  Step 2
  Step 3

Pattern 2: Sentinel Value Loop

Purpose: Process elements until a special “stop” value is encountered.

print("Processing until we find a stop signal:")
data = [10, 20, 30, -1, 40, 50]  # -1 is our "stop" signal
index = 0

print("Processing data until we hit -1:")
while data[index] != -1 and index < len(data):
    print(f" processing: {data[index]}")
    index += 1

if index < len(data):
    print(f"stopped at sentinel value: {data[index]}")


for d in data:
    print(d)
    if d == -1:
        break
    
print(f'stop value: {d}')
Processing until we find a stop signal:
Processing data until we hit -1:
 processing: 10
 processing: 20
 processing: 30
stopped at sentinel value: -1
10
20
30
-1
stop value: -1

Pattern 3: Condition-Based Loop

Purpose: Repeat until a dynamic condition is met (e.g., rolling a dice until a 6 appears).

import random
# random.seed() # For consistent results

current_roll = 0
while current_roll != 6:
    current_roll = random.randint(1,6)
    print(f"Roll: {current_roll}")
Roll: 5
Roll: 6

Pattern 4: Input Validation Loop

Purpose: Keep prompting for input until valid data is received.

print("Simulating input validation:")
valid_inputs = ["yes", "no"]
user_input = ""

while user_input not in valid_inputs:
    user_input = input("Enter 'yes' or 'no': ")
Simulating input validation:
Enter 'yes' or 'no':  hi
Enter 'yes' or 'no':  hello
Enter 'yes' or 'no':  yes

5.4 Try-Except - Handling Errors Gracefully#

Try-except blocks let your program handle errors without crashing. Instead of stopping completely when something goes wrong, you can catch the error and decide what to do.

Basic syntax:

try:
    # Code that might cause an error
    risky_operation()
except:
    # Code to run if an error occurs
    print("Something went wrong!")

Why use try-except?

  • Prevent programs from crashing

  • Provide helpful error messages to users

  • Continue running even when some operations fail

  • Handle expected problems gracefully

input = None
try:
    result = 10 / input
    print(result)
except:
    print('error happens')
print("code termination")
error happens
code termination
try:
    result = 10 / 0
    print(result)
except ZeroDivisionError:
    print("Oops! You can't divide by zero.")
Oops! You can't divide by zero.
print("With error handling:")
velocity = 5.0  # m/s
area = 0  # m² (blocked pipe)

try:
    flow_rate = velocity * area / area  # Division by zero
    print(f"Flow rate: {flow_rate} m³/s")
except ZeroDivisionError:
    print("⚠️ Error: Cannot calculate - pipe appears blocked (area = 0)")
    print("Check for obstruction or sensor malfunction")
    flow_rate = 0

print(f"Program continues... flow_rate = {flow_rate} m³/s")
With error handling:
⚠️ Error: Cannot calculate - pipe appears blocked (area = 0)
Check for obstruction or sensor malfunction
Program continues... flow_rate = 0 m³/s
# Basic Try-Except Examples

print("=== Example 1: Safe Flow Rate Calculation ===")
print("Calculating volumetric flow rate: Q = v × A")
print("Without error handling (would crash):")
print("# Q = 5.0 / 0  # ZeroDivisionError if area is 0")

print("\nWith error handling:")
velocity = 5.0  # m/s
area = 0  # m² (blocked pipe)

try:
    flow_rate = velocity * area / area  # Division by zero
    print(f"Flow rate: {flow_rate} m³/s")
except ZeroDivisionError:
    print("⚠️ Error: Cannot calculate - pipe appears blocked (area = 0)")
    print("Check for obstruction or sensor malfunction")
    flow_rate = 0

print(f"Program continues... flow_rate = {flow_rate} m³/s")

print("\n=== Example 2: Molecular Weight Calculation ===")
user_inputs = ["18.015", "44.01", "invalid", "32.00", "not_a_number"]

for molecular_formula in ["H2O", "CO2", "NaCl", "O2", "CH4"]:
    user_input = user_inputs[["H2O", "CO2", "NaCl", "O2", "CH4"].index(molecular_formula)]
    
    print(f"\nEntering molecular weight for {molecular_formula}: '{user_input}'")
    try:
        MW = float(user_input)
        mass_of_moles = MW * 2  # Calculate mass of 2 moles
        print(f"  ✅ MW = {MW} g/mol")
        print(f"  Mass of 2 moles: {mass_of_moles:.2f} g")
    except ValueError:
        print(f"  ❌ Error: '{user_input}' is not a valid number")
        print(f"  Using default MW from database...")

print("\n=== Example 3: Array Index Safety ===")
temperatures = [25.0, 30.5, 28.3]  # °C
indices_to_check = [0, 1, 2, 5, -1]

print(f"Temperature array: {temperatures}")

for idx in indices_to_check:
    print(f"\nAccessing index {idx}:")
    try:
        temp = temperatures[idx]
        print(f"  ✅ temperatures[{idx}] = {temp}°C")
    except IndexError:
        print(f"  ❌ Error: Index {idx} out of range")
        print(f"  Valid indices: 0 to {len(temperatures)-1}")

print("\n=== Example 4: Reading Sensor Data Files ===")
data_files = ["reactor_temp.csv", "pressure_log.csv", "missing_file.csv"]

for filename in data_files:
    print(f"\nAttempting to read '{filename}':")
    try:
        # Simulate file reading
        if filename != "missing_file.csv":
            data = "25.3,26.1,25.8,26.0"  # Simulated data
            print(f"  ✅ File read successfully")
            print(f"  Data preview: {data[:30]}...")
        else:
            raise FileNotFoundError(f"'{filename}' not found")
    except FileNotFoundError as e:
        print(f"  ❌ Error: {e}")
        print(f"  Check if sensor is logging data properly")

5.4.1 Advanced Try-Except Techniques#

Let’s explore more sophisticated error handling techniques that make your programs more robust.

Multiple Exception Types

Python allows multiple except blocks to handle different error types specifically. This pattern is useful when a block of code may raise different kinds of exceptions, and you want custom handling for each.

Example errors shown:

  • ZeroDivisionError → dividing by zero

  • ValueError → invalid data conversion

  • IndexError → accessing a list out of bounds

  • Exception → catch-all for unexpected errors

print("=== Multiple Exception Types ===")
# List of operations with simpler examples
operations = [
    ("10 / 2", 10 / 2),
    ("10 / 0", "10 / 0"),         # We'll handle this in try
    ("int('abc')", "int('abc')"), # Will raise ValueError
    ("[1,2,3][10]", "list index out of range")  # Will raise IndexError
]

for description, operation in operations:
    print(f"\nTrying: {description}")
    try:
        if description == "10 / 0":
            result = 10 / 0
        elif description == "int('abc')":
            result = int('abc')
        elif description == "[1,2,3][10]":
            result = [1, 2, 3][10]
        else:
            result = operation

        print(f"  ✅ Success: {result}")
    
    except ZeroDivisionError:
        print("  ❌ Cannot divide by zero")
    except ValueError:
        print("  ❌ Invalid value for conversion")
    except IndexError:
        print("  ❌ Index out of range")
    except Exception as e:
        print(f"  ❌ Unexpected error: {e}")
Trying: 10 / 2
  ✅ Success: 5.0

Trying: 10 / 0
  ❌ Cannot divide by zero

Trying: int('abc')
  ❌ Invalid value for conversion

Trying: [1,2,3][10]
  ❌ Index out of range

Try-Except-Else-Finally

Explanation:

  • try → code that may raise an exception

  • except → code executed if an exception occurs

  • else → runs only if no exception occurs

  • finally → runs regardless of whether an exception occurred or not

Benefits:

  • else keeps successful code separate from error handling

  • finally ensures cleanup actions (like closing files) always run

print("\n=== Simple Try-Except-Else-Finally Example ===")

def divide(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        print("  ❌ Cannot divide by zero!")
    else:
        print(f"  ✅ Division successful: {a} / {b} = {result}")
    finally:
        print("  🔄 This always runs")

# Simple test cases
divide(10, 2)  # Successful division
divide(5, 0)   # Division by zero
=== Simple Try-Except-Else-Finally Example ===
  ✅ Division successful: 10 / 2 = 5.0
  🔄 This always runs
  ❌ Cannot divide by zero!
  🔄 This always runs

5.5 Break and Continue - Controlling Loop Flow#

Break and continue give you fine control over how loops behave:

  • break: Exit the loop immediately, no matter what

  • continue: Skip the rest of the current iteration and jump to the next one

These work in both for and while loops and are incredibly useful for handling special cases.

print("Using break:")
for i in range(1, 6):
    if i == 4:
        break  # Stop the loop
    print(i)

print("\nUsing continue:")
for i in range(1, 6):
    if i % 2 == 0:
        continue  # Skip even numbers
    print(i)
print("=== Example 1: Using break to Exit Early ===")
print("Looking for the first even number:")

numbers = [1, 3, 7, 8, 11, 12, 15]
found_even = None

for number in numbers:
    print(f"  Checking {number}...")
    if number % 2 == 0:
        print(f"  🎯 Found first even number: {number}")
        found_even = number
        break  # Exit the loop immediately
    else:
        print(f"    {number} is odd, continue searching...")

if found_even:
    print(f"Search complete! First even number was {found_even}")
else:
    print("No even numbers found")
=== Example 1: Using break to Exit Early ===
Looking for the first even number:
  Checking 1...
    1 is odd, continue searching...
  Checking 3...
    3 is odd, continue searching...
  Checking 7...
    7 is odd, continue searching...
  Checking 8...
  🎯 Found first even number: 8
Search complete! First even number was 8
print("\n=== Example 2: Using continue to Skip Items ===")
print("Processing only positive numbers:")

numbers = [5, -2, 8, -1, 3, -7, 10]

total = 0
count = 0

for number in numbers:
    if number < 0:
        print(f"  Skipping negative number: {number}")
        continue  # Skip to next iteration
    
    # This code only runs for positive numbers
    print(f"  Processing positive number: {number}")
    total += number
    count += 1

print(f"Sum of positive numbers: {total}")
print(f"Count of positive numbers: {count}")
=== Example 2: Using continue to Skip Items ===
Processing only positive numbers:
  Processing positive number: 5
  Skipping negative number: -2
  Processing positive number: 8
  Skipping negative number: -1
  Processing positive number: 3
  Skipping negative number: -7
  Processing positive number: 10
Sum of positive numbers: 26
Count of positive numbers: 4

5.6 Putting It All Together - Real-World Examples#

Now let’s combine all the control structures we’ve learned to solve realistic problems. These examples show how if-else, loops, try-except, break, and continue work together.

# Example 1: Continuous Stirred Tank Reactor (CSTR) Monitoring System

print("=" * 60)
print("CONTINUOUS STIRRED TANK REACTOR (CSTR) MONITORING")
print("=" * 60)

# Hourly monitoring data
monitoring_data = [
    {"hour": 1, "temp": 85, "conc_out": 0.25, "flow_in": 100, "sensor_status": "ok"},
    {"hour": 2, "temp": 87, "conc_out": 0.22, "flow_in": 105, "sensor_status": "ok"},
    {"hour": 3, "temp": 92, "conc_out": 0.18, "flow_in": 98, "sensor_status": "ok"},
    {"hour": 4, "temp": "error", "conc_out": 0.20, "flow_in": 100, "sensor_status": "fault"},
    {"hour": 5, "temp": 88, "conc_out": 0.21, "flow_in": 102, "sensor_status": "ok"},
    {"hour": 6, "temp": 95, "conc_out": 0.15, "flow_in": 110, "sensor_status": "ok"},
]

# Target parameters
target_temp = 90  # °C
target_conc = 0.20  # mol/L
max_temp = 100  # °C
min_flow = 95  # L/min
max_flow = 115  # L/min

warnings_count = 0
critical_alerts = 0
total_conversion = 0
valid_hours = 0

for entry in monitoring_data:
    hour = entry["hour"]
    temp = entry["temp"]
    conc_out = entry["conc_out"]
    flow_in = entry["flow_in"]
    status = entry["sensor_status"]
    
    print(f"\n⏰ Hour {hour}:00")
    print(f"   Sensor status: {status.upper()}")
    
    # Check sensor status first
    if status != "ok":
        print(f"   ⚠️ SENSOR FAULT DETECTED")
        print(f"   Skipping analysis for this hour")
        warnings_count += 1
        continue
    
    # Handle temperature with error checking
    try:
        temp_value = float(temp)
        print(f"   Temperature: {temp_value}°C (target: {target_temp}°C)")
        
        # Temperature control logic
        if temp_value > max_temp:
            print(f"   🚨 CRITICAL: Temperature exceeds {max_temp}°C!")
            print(f"   ACTION: Emergency cooling activated")
            critical_alerts += 1
        elif temp_value > target_temp + 5:
            print(f"   ⚠️ WARNING: Temperature {temp_value - target_temp:.1f}°C above target")
            print(f"   ACTION: Increase cooling water flow")
            warnings_count += 1
        elif temp_value < target_temp - 5:
            print(f"   ⚠️ WARNING: Temperature {target_temp - temp_value:.1f}°C below target")
            print(f"   ACTION: Increase heat input")
            warnings_count += 1
        else:
            print(f"   ✅ Temperature within acceptable range")
            
    except (ValueError, TypeError):
        print(f"   ❌ ERROR: Invalid temperature reading ({temp})")
        print(f"   Calibrate temperature sensor")
        warnings_count += 1
        continue
    
    # Flow rate check
    print(f"   Feed flow rate: {flow_in} L/min")
    if flow_in < min_flow:
        print(f"   ⚠️ Flow rate below minimum ({min_flow} L/min)")
        warnings_count += 1
    elif flow_in > max_flow:
        print(f"   ⚠️ Flow rate above maximum ({max_flow} L/min)")
        print(f"   Risk of overflow - check pump setting")
        warnings_count += 1
    else:
        print(f"   ✅ Flow rate within operating range")
    
    # Concentration and conversion
    conc_in = 1.0  # mol/L (feed concentration)
    conversion = (conc_in - conc_out) / conc_in
    
    print(f"   Outlet concentration: {conc_out} mol/L")
    print(f"   Conversion: {conversion:.1%}")
    
    if conversion >= 0.75:
        print(f"   ✅ Excellent conversion!")
    elif conversion >= 0.60:
        print(f"   ✓ Acceptable conversion")
    else:
        print(f"   ⚠️ Low conversion - check residence time or catalyst")
        warnings_count += 1
    
    total_conversion += conversion
    valid_hours += 1

# Summary Report
print(f"\n" + "=" * 60)
print("SHIFT SUMMARY REPORT")
print("=" * 60)
print(f"Total monitoring hours: {len(monitoring_data)}")
print(f"Valid data hours: {valid_hours}")
print(f"Warnings issued: {warnings_count}")
print(f"Critical alerts: {critical_alerts}")

if valid_hours > 0:
    avg_conversion = total_conversion / valid_hours
    print(f"Average conversion: {avg_conversion:.1%}")
    
    if avg_conversion >= 0.75:
        performance = "EXCELLENT ⭐"
    elif avg_conversion >= 0.65:
        performance = "GOOD ✓"
    elif avg_conversion >= 0.55:
        performance = "ACCEPTABLE ⚠️"
    else:
        performance = "POOR - NEEDS ATTENTION 🔧"
    
    print(f"Overall performance: {performance}")
else:
    print("⚠️ Insufficient valid data for analysis")

if critical_alerts > 0:
    print(f"\n🚨 ATTENTION: {critical_alerts} critical alert(s) during shift")
    print("Review incident log and implement corrective actions")
============================================================
CONTINUOUS STIRRED TANK REACTOR (CSTR) MONITORING
============================================================

⏰ Hour 1:00
   Sensor status: OK
   Temperature: 85.0°C (target: 90°C)
   ✅ Temperature within acceptable range
   Feed flow rate: 100 L/min
   ✅ Flow rate within operating range
   Outlet concentration: 0.25 mol/L
   Conversion: 75.0%
   ✅ Excellent conversion!

⏰ Hour 2:00
   Sensor status: OK
   Temperature: 87.0°C (target: 90°C)
   ✅ Temperature within acceptable range
   Feed flow rate: 105 L/min
   ✅ Flow rate within operating range
   Outlet concentration: 0.22 mol/L
   Conversion: 78.0%
   ✅ Excellent conversion!

⏰ Hour 3:00
   Sensor status: OK
   Temperature: 92.0°C (target: 90°C)
   ✅ Temperature within acceptable range
   Feed flow rate: 98 L/min
   ✅ Flow rate within operating range
   Outlet concentration: 0.18 mol/L
   Conversion: 82.0%
   ✅ Excellent conversion!

⏰ Hour 4:00
   Sensor status: FAULT
   ⚠️ SENSOR FAULT DETECTED
   Skipping analysis for this hour

⏰ Hour 5:00
   Sensor status: OK
   Temperature: 88.0°C (target: 90°C)
   ✅ Temperature within acceptable range
   Feed flow rate: 102 L/min
   ✅ Flow rate within operating range
   Outlet concentration: 0.21 mol/L
   Conversion: 79.0%
   ✅ Excellent conversion!

⏰ Hour 6:00
   Sensor status: OK
   Temperature: 95.0°C (target: 90°C)
   ✅ Temperature within acceptable range
   Feed flow rate: 110 L/min
   ✅ Flow rate within operating range
   Outlet concentration: 0.15 mol/L
   Conversion: 85.0%
   ✅ Excellent conversion!

============================================================
SHIFT SUMMARY REPORT
============================================================
Total monitoring hours: 6
Valid data hours: 5
Warnings issued: 1
Critical alerts: 0
Average conversion: 79.8%
Overall performance: EXCELLENT ⭐
# Example 2: Chemical Inventory Management System

print("=" * 60)
print("LABORATORY CHEMICAL INVENTORY MANAGEMENT")
print("=" * 60)

# Chemical database
chemicals = {
    "H2SO4": {"stock": 5.0, "min_stock": 2.0, "unit": "L", "hazard": "corrosive", "cost_per_unit": 45.00},
    "NaOH": {"stock": 3.5, "min_stock": 1.5, "unit": "kg", "hazard": "corrosive", "cost_per_unit": 25.00},
    "Acetone": {"stock": 0.0, "min_stock": 1.0, "unit": "L", "hazard": "flammable", "cost_per_unit": 30.00},
    "Ethanol": {"stock": 8.0, "min_stock": 2.0, "unit": "L", "hazard": "flammable", "cost_per_unit": 20.00},
    "HCl": {"stock": "invalid", "min_stock": 1.0, "unit": "L", "hazard": "corrosive", "cost_per_unit": 35.00}
}

# Lab requisition requests
requisitions = [
    {"chemical": "H2SO4", "amount": 2.0},
    {"chemical": "NaOH", "amount": 1.5},
    {"chemical": "Acetone", "amount": 0.5},  # Out of stock
    {"chemical": "Benzene", "amount": 1.0},  # Not in database
    {"chemical": "Ethanol", "amount": 10.0}, # Exceeds stock
    {"chemical": "HCl", "amount": 0.5},      # Invalid stock data
    {"chemical": "H2SO4", "amount": 1.0}     # Should work
]

approved_requests = []
denied_requests = []
total_cost = 0.0
reorder_needed = []

print("\nProcessing requisition requests...\n")

for req_num, request in enumerate(requisitions, 1):
    chemical_name = request["chemical"]
    amount_requested = request["amount"]
    
    print(f"Request #{req_num}: {amount_requested} units of {chemical_name}")
    
    # Check if chemical exists in database
    if chemical_name not in chemicals:
        print(f"   ❌ Chemical '{chemical_name}' not in inventory database")
        denied_requests.append(f"{chemical_name} (not in database)")
        print()
        continue
    
    chemical = chemicals[chemical_name]
    
    try:
        # Validate stock data
        current_stock = float(chemical["stock"])
        min_stock = float(chemical["min_stock"])
        cost_per_unit = float(chemical["cost_per_unit"])
        unit = chemical["unit"]
        hazard = chemical["hazard"]
        
        print(f"   Current stock: {current_stock} {unit}")
        print(f"   Hazard class: {hazard.upper()}")
        
        # Check if chemical is out of stock
        if current_stock == 0:
            print(f"   ❌ OUT OF STOCK")
            denied_requests.append(f"{chemical_name} (out of stock)")
            
            # Add to reorder list if not already there
            if chemical_name not in reorder_needed:
                reorder_needed.append(chemical_name)
            print()
            continue
        
        # Check if enough stock available
        if amount_requested > current_stock:
            print(f"   ⚠️ Insufficient stock (only {current_stock} {unit} available)")
            print(f"   Issuing partial amount: {current_stock} {unit}")
            amount_issued = current_stock
        else:
            amount_issued = amount_requested
        
        # Calculate cost
        request_cost = amount_issued * cost_per_unit
        
        # Update stock
        new_stock = current_stock - amount_issued
        chemicals[chemical_name]["stock"] = new_stock
        
        # Special handling for hazardous materials
        if hazard in ["corrosive", "flammable", "toxic"]:
            print(f"   ⚠️ HAZARD: {hazard.upper()} - Special handling required")
            print(f"   Ensure proper PPE and secondary containment")
        
        # Check if reorder is needed
        if new_stock < min_stock:
            print(f"   📉 Stock below minimum ({min_stock} {unit})")
            if chemical_name not in reorder_needed:
                reorder_needed.append(chemical_name)
                print(f"   Added to reorder list")
        
        # Approve request
        approved_requests.append({
            "chemical": chemical_name,
            "amount": amount_issued,
            "unit": unit,
            "cost": request_cost
        })
        
        total_cost += request_cost
        
        print(f"   ✅ APPROVED: {amount_issued} {unit}")
        print(f"   Cost: ${request_cost:.2f}")
        print(f"   Remaining stock: {new_stock} {unit}")
        
    except (ValueError, TypeError) as e:
        print(f"   ❌ ERROR: Invalid data in database for '{chemical_name}'")
        print(f"   Database entry needs correction")
        denied_requests.append(f"{chemical_name} (database error)")
        print()
        continue
    
    print()

# Generate summary report
print("=" * 60)
print("REQUISITION SUMMARY REPORT")
print("=" * 60)

if len(approved_requests) == 0:
    print("\n⚠️ No requests were approved")
else:
    print(f"\n✅ APPROVED REQUESTS ({len(approved_requests)}):")
    
    # Group by hazard class
    corrosive_items = []
    flammable_items = []
    other_items = []
    
    for req in approved_requests:
        chem = req["chemical"]
        hazard = chemicals[chem]["hazard"]
        
        if hazard == "corrosive":
            corrosive_items.append(req)
        elif hazard == "flammable":
            flammable_items.append(req)
        else:
            other_items.append(req)
    
    # Display by hazard class
    if corrosive_items:
        print(f"\n   🧪 CORROSIVE CHEMICALS:")
        subtotal = 0
        for item in corrosive_items:
            print(f"      • {item['amount']} {item['unit']} {item['chemical']} - ${item['cost']:.2f}")
            subtotal += item['cost']
        print(f"      Subtotal: ${subtotal:.2f}")
    
    if flammable_items:
        print(f"\n   🔥 FLAMMABLE CHEMICALS:")
        subtotal = 0
        for item in flammable_items:
            print(f"      • {item['amount']} {item['unit']} {item['chemical']} - ${item['cost']:.2f}")
            subtotal += item['cost']
        print(f"      Subtotal: ${subtotal:.2f}")
    
    if other_items:
        print(f"\n   📦 OTHER CHEMICALS:")
        subtotal = 0
        for item in other_items:
            print(f"      • {item['amount']} {item['unit']} {item['chemical']} - ${item['cost']:.2f}")
            subtotal += item['cost']
        print(f"      Subtotal: ${subtotal:.2f}")
    
    print(f"\n   TOTAL COST: ${total_cost:.2f}")

# Display denied requests
if denied_requests:
    print(f"\n❌ DENIED REQUESTS ({len(denied_requests)}):")
    for item in denied_requests:
        print(f"   • {item}")

# Display reorder recommendations
if reorder_needed:
    print(f"\n📋 REORDER RECOMMENDATIONS:")
    print(f"The following chemicals are below minimum stock levels:\n")
    reorder_cost = 0
    
    for chem in reorder_needed:
        if chem in chemicals:
            try:
                current = float(chemicals[chem]["stock"])
                minimum = float(chemicals[chem]["min_stock"])
                unit = chemicals[chem]["unit"]
                cost = float(chemicals[chem]["cost_per_unit"])
                
                # Recommend ordering enough to reach 2x minimum stock
                order_amount = max(minimum * 2 - current, 0)
                order_cost = order_amount * cost
                reorder_cost += order_cost
                
                print(f"   • {chem}:")
                print(f"     Current: {current} {unit}, Minimum: {minimum} {unit}")
                print(f"     Recommended order: {order_amount:.1f} {unit} (${order_cost:.2f})")
            except (ValueError, TypeError):
                print(f"   • {chem}: Review database entry")
    
    print(f"\n   Estimated reorder cost: ${reorder_cost:.2f}")

print(f"\nCurrent inventory status:")
for chem, data in chemicals.items():
    try:
        stock = float(data["stock"])
        unit = data["unit"]
        print(f"   {chem}: {stock} {unit}")
    except (ValueError, TypeError):
        print(f"   {chem}: ERROR - invalid data")
============================================================
LABORATORY CHEMICAL INVENTORY MANAGEMENT
============================================================

Processing requisition requests...

Request #1: 2.0 units of H2SO4
   Current stock: 5.0 L
   Hazard class: CORROSIVE
   ⚠️ HAZARD: CORROSIVE - Special handling required
   Ensure proper PPE and secondary containment
   ✅ APPROVED: 2.0 L
   Cost: $90.00
   Remaining stock: 3.0 L

Request #2: 1.5 units of NaOH
   Current stock: 3.5 kg
   Hazard class: CORROSIVE
   ⚠️ HAZARD: CORROSIVE - Special handling required
   Ensure proper PPE and secondary containment
   ✅ APPROVED: 1.5 kg
   Cost: $37.50
   Remaining stock: 2.0 kg

Request #3: 0.5 units of Acetone
   Current stock: 0.0 L
   Hazard class: FLAMMABLE
   ❌ OUT OF STOCK

Request #4: 1.0 units of Benzene
   ❌ Chemical 'Benzene' not in inventory database

Request #5: 10.0 units of Ethanol
   Current stock: 8.0 L
   Hazard class: FLAMMABLE
   ⚠️ Insufficient stock (only 8.0 L available)
   Issuing partial amount: 8.0 L
   ⚠️ HAZARD: FLAMMABLE - Special handling required
   Ensure proper PPE and secondary containment
   📉 Stock below minimum (2.0 L)
   Added to reorder list
   ✅ APPROVED: 8.0 L
   Cost: $160.00
   Remaining stock: 0.0 L

Request #6: 0.5 units of HCl
   ❌ ERROR: Invalid data in database for 'HCl'
   Database entry needs correction

Request #7: 1.0 units of H2SO4
   Current stock: 3.0 L
   Hazard class: CORROSIVE
   ⚠️ HAZARD: CORROSIVE - Special handling required
   Ensure proper PPE and secondary containment
   ✅ APPROVED: 1.0 L
   Cost: $45.00
   Remaining stock: 2.0 L

============================================================
REQUISITION SUMMARY REPORT
============================================================

✅ APPROVED REQUESTS (4):

   🧪 CORROSIVE CHEMICALS:
      • 2.0 L H2SO4 - $90.00
      • 1.5 kg NaOH - $37.50
      • 1.0 L H2SO4 - $45.00
      Subtotal: $172.50

   🔥 FLAMMABLE CHEMICALS:
      • 8.0 L Ethanol - $160.00
      Subtotal: $160.00

   TOTAL COST: $332.50

❌ DENIED REQUESTS (3):
   • Acetone (out of stock)
   • Benzene (not in database)
   • HCl (database error)

📋 REORDER RECOMMENDATIONS:
The following chemicals are below minimum stock levels:

   • Acetone:
     Current: 0.0 L, Minimum: 1.0 L
     Recommended order: 2.0 L ($60.00)
   • Ethanol:
     Current: 0.0 L, Minimum: 2.0 L
     Recommended order: 4.0 L ($80.00)

   Estimated reorder cost: $140.00

Current inventory status:
   H2SO4: 2.0 L
   NaOH: 2.0 kg
   Acetone: 0.0 L
   Ethanol: 0.0 L
   HCl: ERROR - invalid data

Summary#

In this chapter, you learned how to control the flow of your programs:

Boolean Logic#

  • Boolean values: True and False

  • Comparison operators: ==, !=, >, <, >=, <=

  • Logical operators: and, or, not

Decision Making#

  • if statements: Execute code when condition is True

  • if-else: Choose between two options

  • if-elif-else: Choose among multiple options

Loops#

  • for loops: Repeat for each item in a sequence

  • while loops: Repeat while a condition is True

  • break: Exit a loop early

  • continue: Skip to next iteration