0%

Where to Go Next · practice

Read and Adapt a Complete Program

Reading code is a separate skill from writing it. A complete unfamiliar program can look dense even when every individual feature is familiar.

Use a repeatable reading order.

1. Find the data

Consider:

scores = [
    {"name": "Ari", "points": 12},
    {"name": "Bo", "points": 19},
]

This is a of consistently shaped records. Before reading any , you know what one item looks like.

2. Read function contracts from the outside

def highest_score(scores):
    pass

The name suggests one selected result. The single receives the collection.

Look at the return statements next. Does the return a record, a number, a , or None?

3. Trace one small call

For a selection loop:

best = None

for score in scores:
    if best is None or score["points"] > best["points"]:
        best = score

Trace two records:

IterationCurrent recordbest afterward
1Ari, 12Ari, 12
2Bo, 19Bo, 19

The best is None gives the first record a place to start. Python checks the left side of or first. When it is true, Python already knows the whole condition is true, so it skips the right side. On the first pass, that means it never tries to read best["points"] while best is None.

On later passes, best holds a record, so the left side is false and Python evaluates the comparison on the right. A later record replaces best only when its points are greater. This left-to-right skipping is called short-circuit evaluation.

4. Follow the callers

If a formatting function calls highest_score, identify which returned fields it uses.

This reveals the program’s chain:

records -> selection function -> selected record -> formatted report

Retrieve a familiar report boundary

A formatting function may keep its complete lines in a list and return them as one string:

lines = [f"Busiest: {busiest['name']}"]
return "\n".join(lines)

Before reading on, explain the call to yourself. Why is "\n" before .join(), why is lines the , and what kind of comes back?

The same rule from the refactoring lesson applies here: the string before the dot is the separator, the argument supplies a list of strings, and the result is one string. When you extend this report, add another complete string to lines and preserve that boundary.

5. Establish a baseline before editing

Run the starter exactly as it is. Record its current output.

When a new requirement arrives, preserve that baseline unless the requirement explicitly changes it.

Make the smallest accurate extension

Suppose the program must also report the lowest score. A focused extension is:

  • add a second selection function with the same record contract;

  • call both selectors from the report;

  • keep the existing highest string in lines unchanged;

  • add one new lowest string before the list is joined.

A complete rewrite is unnecessary. Accurate reading lets you change the smallest responsible area.

When first reading an unfamiliar record-processing program, what is a useful early question?

Task

Read the complete visitor-report program before editing it. Run the starter and identify:

  • the shape of one day record;

  • what busiest_day(days) returns;

  • how format_report(days) turns its of report into one string.

Then make one focused extension:

  1. Add quietest_day(days) using the same record-returning contract.

  2. Update format_report(days) to preserve its existing busiest string and add the quietest string to lines.

  3. Keep returning the report with "\n".join(lines).

  4. Keep the prepared data and final print.

The final output must be:

Busiest: Saturday (42)
Quietest: Monday (12)

Both selection must work for other non-empty day lists, including a list with one record. When visitor counts tie, keep the first matching record, as the existing busiest_day comparison does.