Solutions
Lab Solutions
Reference solutions in Python. There's always more than one correct answer — if a student's version produces the right output and reads clearly, it's right. Teaching notes are in bold.
Lab 1 — Variables & Data Types
# 1. Variables of each core type
name = "Ada"
age = 25
gpa = 3.8
is_enrolled = True
# 2. Print a sentence (f-string is the readable, modern way)
print(f"{name} is {age} years old, GPA {gpa}, enrolled: {is_enrolled}")
# 3. The bug
age_text = "25"
# print(age_text + 5) # TypeError: can only concatenate str (not "int") to str
# 4. The fix — convert text to a number first
print(int(age_text) + 5) # 30Teaching note: Task 3 is the point of the whole lab.
"25" looks like a number but is text; Python
refuses to add text and a number. int("25") converts it.
This is exactly what happens when data arrives from a CSV/form as
strings — converting types correctly is data cleaning.
Stretch:
print(type(name), type(age), type(gpa), type(is_enrolled))
# <class 'str'> <class 'int'> <class 'float'> <class 'bool'>
print(0.1 + 0.2) # 0.30000000000000004 -> floats are approximate; never compare with ==Lab 2 — Control Flow (mini FizzBuzz)
Final version (steps 1–3 combined):
for n in range(1, 21):
if n % 3 == 0 and n % 5 == 0: # check BOTH first
print("FizzBuzz")
elif n % 3 == 0:
print("Fizz")
elif n % 5 == 0:
print("Buzz")
else:
print(n)Teaching note: Why check "both" first?
Because 15 is a multiple of 3 and 5. If
you tested n % 3 == 0 first, 15 would print
"Fizz" and never reach the FizzBuzz case. Order of
conditions is a real source of bugs — the most specific case
goes first.
Stretch — while version:
n = 1
while n <= 20:
# ... same if/elif/else ...
n += 1 # <- forget this line and you get an INFINITE loopLab 3 — Functions
def is_even(n):
return n % 2 == 0 # the comparison is already a boolean
def grade(score):
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
else:
return "F"
print(is_even(4)) # True
print(is_even(7)) # False
print("Score 85 is even:", is_even(85), "and gets a", grade(85))
# Score 85 is even: False and gets a BTeaching note: return n % 2 == 0
surprises beginners who expect an if/else. Stress that a
comparison is a boolean, so you can return it directly. Note
how grade(85)'s return value flows straight into
print — functions composing is the whole game.
Stretch — default parameter & scope:
def grade(score, passing=70):
return "PASS" if score >= passing else "FAIL"
def grade2(score):
letter = "A" # local variable
return letter
# print(letter) # NameError: 'letter' is not defined -> it only exists INSIDE the function (scope)Lab 4 — Capstone: Tiny Gradebook
def grade(score):
if score >= 90: return "A"
elif score >= 80: return "B"
elif score >= 70: return "C"
else: return "F"
students = [
{"name": "Ada", "score": 92},
{"name": "Linus", "score": 78},
{"name": "Grace", "score": 85},
{"name": "Alan", "score": 64},
]
# 2. Per-student report
for s in students:
print(f"{s['name']:<6} | {s['score']} | {grade(s['score'])}")
# 3. Class average
scores = [s["score"] for s in students] # a list comprehension — pull out every score
avg = sum(scores) / len(scores)
print(f"Class average: {avg:.1f}") # 79.8
# 4. How many passed
passed = 0
for s in students:
if s["score"] >= 70:
passed += 1
print(f"Passed: {passed} / {len(students)}") # 3 / 4Output:
Ada | 92 | A
Linus | 78 | C
Grace | 85 | B
Alan | 64 | F
Class average: 79.8
Passed: 3 / 4
Stretch:
top = students[0]
for s in students:
if s["score"] > top["score"]:
top = s
print(f"Top student: {top['name']} ({top['score']})") # Ada (92)Teaching note: Narrate how every concept from the day appears here:
- list of dicts = a dataset (rows of records),
forloop = process each row,grade()function = reusable logic,ifinside the count = a decision,sum/len+ division = type-aware math,- f-strings with
:<6/:.1f= formatting output.
Swap students for rows read from a real CSV and they've
written their first data pipeline — exactly the shape of practical
AI/data work.