Come Back Later: Review Challenges

The Course
•
September 24, 2026
•
5 min read

Finishing a course and being able to use what it taught are different things, and the gap shows up a week later. Things you understood perfectly on the day turn out to be half-remembered, which is normal — and the cure is exactly what it sounds like: coming back and trying again, without rereading first.

Bookmark this page. Come back in about a week for the first set, and in about a month for the second. Those gaps are a sensible starting point, not a magic schedule; if you come back sooner or later, it still helps.

How to use it:

  • Try each one from memory first. Reopening the lesson before you try skips the part that does the work.
  • Use the hints to check, not to start. Each one names the lesson it comes from.
  • Keep a list of the ones you needed help with. That list is precisely the set of lessons worth rereading — which is more useful than rereading all of them.

A week later

1. Predict both lines.

Week 1: predict Python
scores = {"ada": [90, 85], "alan": [70], "grace": [88, 92, 79]}
averages = {name: sum(s) / len(s) for name, s in scores.items()}

print(sorted(averages, key=lambda name: averages[name], reverse=True))
print(round(averages["grace"], 1))
Check your prediction
['ada', 'grace', 'alan']
86.3

A dictionary comprehension, then sorted with a key — sorting a dictionary sorts its keys, and the key function decides the order. From Comprehensions and Scope & Lambdas.

2. Fix. When the file doesn’t exist, this should print [] rather than crash.

Week 1: fix Python
def load_lines(path):
    with open(path) as file:
        return [line.strip() for line in file]

print(load_lines("missing.txt"))
Check your fix
def load_lines(path):
    try:
        with open(path) as file:
            return [line.strip() for line in file]
    except FileNotFoundError:
        return []

print(load_lines("missing.txt"))
[]

Catch the one exception you expect, and decide what “no file” should mean. From Reading & Writing Files and Errors & Exceptions.

3. Write long_words(text): it returns a dictionary of each word longer than three letters, lower-cased, mapped to its length. This should print {'quick': 5, 'brown': 5}:

Week 1: write Python
# def long_words(text): ...

print(long_words("The Quick brown fox"))
Check your answer
def long_words(text):
    return {word.lower(): len(word) for word in text.split() if len(word) > 3}

print(long_words("The Quick brown fox"))
{'quick': 5, 'brown': 5}

A dictionary comprehension with a filter at the end. From Comprehensions.

4. Explain. No code: in two sentences, why does def add(item, items=[]) cause trouble, and what’s the fix?

Check your explanation

The default list is created once, when the function is defined, so every call that relies on the default shares — and keeps adding to — the same list. Use items=None and create a fresh list inside the function when it’s None.

From Defining Functions. If your explanation said the same thing in different words, that counts.

A month later

1. Predict both lines.

Month 1: predict Python
from dataclasses import dataclass

@dataclass
class Task:
    title: str
    priority: int
    done: bool = False

tasks = [Task("email", 2), Task("report", 1), Task("lunch", 3, True)]
todo = [t.title for t in sorted(tasks, key=lambda t: t.priority) if not t.done]

print(todo)
print(tasks[0])
Check your prediction
['report', 'email']
Task(title='email', priority=2, done=False)

Sorted by priority, then the done task filtered out. sorted makes a new list, so tasks[0] is still the first task you wrote. From Dataclasses, Comprehensions and Lists.

2. Fix. This should print each word that appears more than once — once each, in order: ['a', 'b'].

Month 1: fix Python
seen = []
duplicates = []

for word in "a b a c b a".split():
    if word in seen:
        duplicates.append(word)
    seen.append(word)

print(duplicates)
Check your fix
seen = set()
duplicates = set()

for word in "a b a c b a".split():
    if word in seen:
        duplicates.add(word)
    seen.add(word)

print(sorted(duplicates))
['a', 'b']

“Once each” is a uniqueness question, which is what sets are for — and in on a set stays fast however long the text gets. From Sets & Choosing a Collection.

3. Write a Budget class so that the code below prints the two lines shown after it. spend must refuse — with a ValueError saying by how much — any amount that would go over the limit.

Month 1: write Python
# class Budget: ...

budget = Budget(100)
budget.spend(60)
try:
    budget.spend(50)
except ValueError as error:
    print("refused:", error)
print(budget.remaining())
refused: over budget by 10
40
Check your answer
class Budget:
    def __init__(self, limit):
        self.limit = limit
        self.spent = 0

    def spend(self, amount):
        if self.spent + amount > self.limit:
            raise ValueError(f"over budget by {self.spent + amount - self.limit}")
        self.spent += amount

    def remaining(self):
        return self.limit - self.spent

budget = Budget(100)
budget.spend(60)
try:
    budget.spend(50)
except ValueError as error:
    print("refused:", error)
print(budget.remaining())
refused: over budget by 10
40

The check comes before the change, so a refused amount leaves the budget as it was. From Classes & Objects and Errors & Exceptions.

4. Explain. No code: you’ve written a function. Name four kinds of case worth testing it with.

Check your explanation

A typical case; the boundaries — zero, empty, one; something invalid, and the error it should raise; and any bug you’ve ever fixed in it, so it can’t come back. From Testing Your Code.

After that

If these came easily, the best thing you can do next is build something — the briefs at the end of On Your Own are a good start. If some didn’t, you now know exactly which lessons to reread, and rereading three lessons on purpose beats rereading all of them.

Last updated on September 24, 2026

Was this article helpful?

Your response is saved on this device.