Chapter 3 — Control Flow: Selections and Loops
Programs make decisions and repeat work. This chapter covers conditional statements (if/elif/else), loops (while, for), and the random module — essential tools for transforming and simulating data.
Learning Objectives
- Build Boolean expressions with
and,or,not. - Write
if,if-else, and multi-wayif-elif-elsestatements. - Use conditional expressions for concise logic.
- Generate random numbers with the
randommodule. - Write
whileandforloops, including nested loops. - Control loops with
breakandcontinue. - Recognize and minimize floating-point accumulation errors.
Prerequisites / Imports
Uses the standard random module.
import random
random.seed(42)
1 Boolean Expressions and Logical Operators
Comparisons produce Booleans; combine them with and, or, not.
score = 78
print(60 <= score < 90) # chained comparison
print(score >= 90 or score < 60)
print(not score == 100)
True False True
2 if, if-else, and if-elif-else
Indentation defines the block. Multi-way branching uses elif.
score = 78
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
elif score >= 70:
grade = 'C'
elif score >= 60:
grade = 'D'
else:
grade = 'F'
print('Grade:', grade)
Grade: C
3 Common Selection Errors
Using = (assignment) instead of == (comparison) is a classic bug. Mismatched indentation changes meaning. Always test boundary values.
# Correct comparison
x = 5
if x == 5:
print('x is 5')
x is 5
4 Conditional Expressions
A one-line x if condition else y returns a value.
age = 17
status = 'adult' if age >= 18 else 'minor'
print(status)
minor
5 Generating Random Numbers
The random module is indispensable for simulation and synthetic data.
print('random float [0,1):', random.random())
print('random int 1..6:', random.randint(1, 6))
print('choice:', random.choice(['heads','tails']))
print('sample of 3:', random.sample(range(1, 50), 3))
random float [0,1): 0.6394267984578837 random int 1..6: 1 choice: tails sample of 3: [16, 15, 9]
6 while Loops
while repeats as long as a condition holds. Use it for sentinel-controlled or unknown-iteration tasks.
# Countdown with a while loop
n = 5
while n > 0:
print(n)
n -= 1
print('Liftoff!')
5 4 3 2 1 Liftoff!
7 for Loops
for iterates over a sequence or range. It is the workhorse for processing collections.
for i in range(5):
print(i, 'squared =', i*i)
0 squared = 0 1 squared = 1 2 squared = 4 3 squared = 9 4 squared = 16
# Accumulating a sum
total = 0
for i in range(1, 101):
total += i
print('Sum 1..100 =', total)
Sum 1..100 = 5050
8 Nested Loops
Loops inside loops handle grids and combinations. Keep nesting shallow for readability.
# Multiplication table (3x5)
for i in range(1, 4):
row = []
for j in range(1, 6):
row.append(i * j)
print(row)
[1, 2, 3, 4, 5] [2, 4, 6, 8, 10] [3, 6, 9, 12, 15]
9 break and continue
break exits the enclosing loop; continue skips to the next iteration.
# Find first number divisible by 7 between 1 and 100
for n in range(1, 101):
if n % 7 == 0:
print('First multiple of 7:', n)
break
First multiple of 7: 7
# Skip odd numbers, print evens up to 10
for n in range(11):
if n % 2 != 0:
continue
print(n)
0 2 4 6 8 10
10 Minimizing Numerical Errors
Repeatedly adding small floats accumulates error. Prefer larger increments or use math.fsum.
# Naive accumulation
s = 0.0
for _ in range(100000):
s += 0.0001
print('naive sum:', s)
# Accurate accumulation
import math
s2 = math.fsum([0.0001] * 100000)
print('fsum: ', s2)
naive sum: 9.999999999990033 fsum: 10.0
Case Study: Loan Approval Decision Logic
Apply rule-based approval to a small synthetic set of applicants and count outcomes.
random.seed(0)
applicants = []
for i in range(10):
applicants.append({
'id': i+1,
'credit': random.randint(500, 850),
'income': random.randint(20000, 120000),
'dti': round(random.uniform(0.05, 0.45), 2),
})
def decide(a):
if a['credit'] >= 700 and a['dti'] < 0.36 and a['income'] >= 30000:
return 'approve'
elif a['credit'] >= 650 and a['dti'] < 0.43:
return 'manual review'
else:
return 'deny'
results = {}
for a in applicants:
decision = decide(a)
results[decision] = results.get(decision, 0) + 1
print(f"Applicant {a['id']:>2}: credit={a['credit']} income=${a['income']} dti={a['dti']} -> {decision}")
print('\nSummary:', results)
Applicant 1: credit=697 income=$119346 dti=0.41 -> manual review
Applicant 2: credit=520 income=$53936 dti=0.44 -> deny
Applicant 3: credit=748 income=$73075 dti=0.42 -> manual review
Applicant 4: credit=655 income=$82468 dti=0.19 -> manual review
Applicant 5: credit=611 income=$86150 dti=0.11 -> deny
Applicant 6: credit=571 income=$119064 dti=0.09 -> deny
Applicant 7: credit=628 income=$89804 dti=0.44 -> deny
Applicant 8: credit=808 income=$39262 dti=0.17 -> approve
Applicant 9: credit=537 income=$109651 dti=0.18 -> deny
Applicant 10: credit=786 income=$33199 dti=0.19 -> approve
Summary: {'manual review': 3, 'deny': 5, 'approve': 2}
Exercises
- Classify a BMI value as underweight, normal, overweight, or obese using
if-elif-else. - Simulate rolling two dice 1000 times and count how many doubles occur.
- Determine whether a year is a leap year (divisible by 4, not 100 unless also 400).
- Print all prime numbers between 2 and 50 using nested loops and
break. - Use a
whileloop to sum integers until the running total exceeds 100. - Generate 20 random salaries and count how many exceed $60,000.
- Rewrite a simple
if-elseas a conditional expression. - Show the difference between naive float summation and
math.fsumfor 0.1 added 1,000,000 times. - Write a number-guessing loop with a fixed target (no
input()); print each guess until correct. - Use nested loops to print a 4x4 grid of random 0/1 values.
Python Data Science: From Foundations to Applications — Chapter 3