Unit 08 · lesson

Choose the Structure Before You Fight It

Core path: 30 minutes

A lot of beginner code becomes awkward because the data structure was chosen by habit instead of by the shape of the problem.

The code still runs. It just spends the rest of the project compensating for a bad decision made near the beginning.

This lesson is about making that decision deliberately.

Strings, lists, and dictionaries solve different problems

A string is an ordered sequence of characters:

callsign = "NOVA"

A list is an ordered collection of items:

players = ["Nova", "Maya", "Kai"]

A dictionary maps keys to values:

player = {
    "name": "Nova",
    "score": 850,
    "online": True,
}

The question is not which structure is "best."

Ask what relationship the data has.

Use position when position matters

A list makes sense when order is useful:

checkpoints = ["A", "B", "C", "D"]

Then:

checkpoints[0]

means the first item.

If the meaning of the item is mostly its position, indexing is natural.

But imagine storing a player like this:

player = ["Nova", 850, True]

What does player[1] mean six weeks from now?

You have to remember the hidden convention:

index 0 → name
index 1 → score
index 2 → online

A dictionary makes that meaning explicit:

player["score"]

The code explains itself better.

Use keys when fields have names

A dictionary is a good fit for one structured record:

robot = {
    "name": "Rover-01",
    "battery": 82,
    "mode": "AUTO",
}

The keys communicate the schema of the record.

That does not mean dictionaries should replace every list. A roster is still naturally a list of player dictionaries because you have multiple records:

players = [
    {"name": "Nova", "score": 850},
    {"name": "Maya", "score": 960},
]

Outside structure: collection.

Inside structure: record.

Mutation changes the collection you already have

Strings behave differently from lists.

This fails:

word = "ROBOT"
word[0] = "X"

Strings are immutable. You create a new string instead of replacing one character in place.

Lists are mutable:

players = ["Nova", "Maya"]
players[0] = "Kai"

Now the existing list has changed.

That difference matters because code elsewhere may still be referring to the same list object.

Two names can point at the same list

Consider:

players = ["Nova", "Maya"]
backup = players
backup.append("Kai")

print(players)

What prints?

['Nova', 'Maya', 'Kai']

backup = players did not create a new independent list. Both names refer to the same list object.

If you actually need a shallow copy:

backup = players.copy()

Now appending to backup does not change players.

This is one of those moments where the variable-as-a-box metaphor starts causing trouble. Names can refer to objects, and more than one name can refer to the same object.

Build the wrong version on purpose

Take one player from Lesson 4 and rewrite it as a list:

player = ["Nova", 850, "ADVANCED", True]

Then write the code needed to display the score and online state.

Now compare it with:

player = {
    "name": "Nova",
    "score": 850,
    "rank": "ADVANCED",
    "online": True,
}

Which version communicates the record more clearly to another developer?

Do not answer from aesthetics. Point to the exact access expressions.

Structure should make later operations easier

For each scenario, choose a structure and explain why:

A robot callsign

"RVR-07"

Ordered lap times

[61.2, 59.8, 60.4]

One robot status record

name, battery, mode, temperature

A fleet of robot status records

Think about the outer and inner structures separately.

Review your roster

Look at the Player Roster Manager from Lesson 4.

For each of these, explain the structure choice:

players → why a list?
player → why a dictionary?
player["name"] → why a key instead of an index?
name string → why a string?

Then identify one operation the current structure makes easy and one operation that would become awkward if the data were stored differently.

That is what data-structure choice really means.

You are deciding which relationships the code should make obvious.

Reader workbench

Defend the data structure with behavior

This is the Unit's one-file practice surface. Read the code, predict one result, run it, then change a value, input, condition, or boundary and explain why the evidence changed. Multi-file projects, Git, terminals, packages, and live services still belong in the full development workspace.

unit08_practice.py
OutputRun with button or Ctrl/Cmd+Enter
Run the code to see output.
Ready to edit. Press Run when you want evidence.

This runs in an isolated Python worker in your browser. Your edits stay in this browser until you reset them.