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:
if-else statements (making decisions)
for loops (repeating with sequences)
while loops (repeating with conditions)
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
TrueorFalsePython uses indentation (4 spaces) to define code blocks
All indented lines after the
ifbelong 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
rangeis a built-in Python function that generates a sequence of integers.
It starts from a given value (default is0), stops before the end value,
and can optionally increment by a specified step size.
rangeis commonly used to control how many times aforloop 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 |
|
|
|---|---|---|
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 |
|
|
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 zeroValueError→ invalid data conversionIndexError→ accessing a list out of boundsException→ 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 exceptionexcept→ code executed if an exception occurselse→ runs only if no exception occursfinally→ runs regardless of whether an exception occurred or not
Benefits:
elsekeeps successful code separate from error handlingfinallyensures 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 whatcontinue: 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:
TrueandFalseComparison operators:
==,!=,>,<,>=,<=Logical operators:
and,or,not
Decision Making#
ifstatements: Execute code when condition is Trueif-else: Choose between two optionsif-elif-else: Choose among multiple options
Loops#
forloops: Repeat for each item in a sequencewhileloops: Repeat while a condition is Truebreak: Exit a loop earlycontinue: Skip to next iteration