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

Prerequisites / Imports

Uses the standard random module.

In [1]:
import random
random.seed(42)

1 Boolean Expressions and Logical Operators

Comparisons produce Booleans; combine them with and, or, not.

In [1]:
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.

In [1]:
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.

In [1]:
# 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.

In [1]:
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.

In [1]:
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.

In [1]:
# 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.

In [1]:
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
In [1]:
# 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.

In [1]:
# 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.

In [1]:
# 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
In [1]:
# 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.

In [1]:
# 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.

In [1]:
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

  1. Classify a BMI value as underweight, normal, overweight, or obese using if-elif-else.
  2. Simulate rolling two dice 1000 times and count how many doubles occur.
  3. Determine whether a year is a leap year (divisible by 4, not 100 unless also 400).
  4. Print all prime numbers between 2 and 50 using nested loops and break.
  5. Use a while loop to sum integers until the running total exceeds 100.
  6. Generate 20 random salaries and count how many exceed $60,000.
  7. Rewrite a simple if-else as a conditional expression.
  8. Show the difference between naive float summation and math.fsum for 0.1 added 1,000,000 times.
  9. Write a number-guessing loop with a fixed target (no input()); print each guess until correct.
  10. Use nested loops to print a 4x4 grid of random 0/1 values.

Python Data Science: From Foundations to Applications — Chapter 3