Day 4 ยท Bookshelves and dictionaries

Collections

You will be able to
  • Choose the right structure โ€” list, tuple, set, or dict โ€” for a given job and justify it
  • Index and slice lists and strings without off-by-one errors
  • Explain aliasing: predict when two names see the same mutation
  • Build and query dicts, including safe lookup with .get and iteration over items
  • Rewrite simple loops as list and dict comprehensions
Today's ~120 minutes
Spaced-rep warm-up: Days 1โ€“3 flashcards10 min
Concept study: ELI5 + tech, with the cells-index visualizer20 min
Guided: shelf lab, aliasing lab, dicts & comprehensions45 min
Practice: the gradebook20 min
Project: study-log data model15 min
Quiz + flashcards10 min

Builds on: Day 2 โ€” Variables, types, and loops ยท Day 3 โ€” Functions and return values

The analogy

A list is a bookshelf: books in a fixed order, each slot numbered (starting at 0, the ground floor), and you fetch a book by its position โ€” "give me shelf slot 2." You can add books, remove them, or swap one out; the shelf itself stays put. A tuple is a shelf sealed behind glass: same idea, but nothing can be added or swapped after it's built โ€” great for things that must not change. A dict works like a real dictionary: you don't ask for "the word on page 305," you ask for "the definition of *serendipity*" โ€” you look things up by a meaningful key, not a position. And a set is a bag that refuses duplicates: throw in "apple" twice, it keeps one โ€” perfect for "have I seen this before?"

One warehouse warning from Day 2's labels-on-boxes: two labels can point at the *same shelf*. If your friend rearranges the books using their label, your label sees the rearranged shelf too โ€” because there is only one shelf. That's aliasing, and it's today's most valuable lesson.

Why this matters on the job

Choosing structures is half of programming. The interview classic "why is your code slow?" is usually "you used a list where a set/dict belonged" โ€” that exact trade-off gets a price tag on Day 22 (Big O) and powers the hashing patterns of Day 23. Everything you'll touch as an AI engineer is nested lists-and-dicts: every JSON API response (Day 41), every LLM chat request โ€” a list of message dicts (Day 106) โ€” every RAG chunk with its metadata (Day 114). Aliasing bugs, meanwhile, are the classic "my function mysteriously changed my caller's data" production incident. Learn to see references today and that bug loses its magic.

Watch it happen

The bookshelf โ€” indexing and slicing a list

step 1 / 6
langs[0]
py
0
sql
1
go
2
js
3
rs
4

A list is a numbered shelf. Positions start at 0 โ€” the first item is langs[0], not langs[1].

Guided practice

guided 1

The shelf lab โ€” indexing, slicing, mutating

15 min
  1. Create week-01/shelves.py with the starter code. Before running each section, write your predicted output as a comment โ€” the visualizer view (cells-index) shows the numbered slots if you want to check your mental picture.
  2. Section 1: verify the negative-index and slicing predictions. Then answer in a comment: why does nums[1:3] contain two items, not three?
  3. Section 2: run the sort trap. Explain in a comment what mystery is and why.
  4. Section 3: practice mutations โ€” append a value, pop the last, insert at the front, remove by value. Print after each so you can watch the shelf change.
  5. Finish with: build a list of the first 10 square numbers using a loop and .append(). Keep it โ€” you'll rewrite it as a comprehension in exercise 3.
๐Ÿ python โ€” editable, runs in your browser
Ctrl/โŒ˜+Enter runs ยท Tab indents ยท numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)
guided 2

One shelf, two labels โ€” the aliasing lab

15 min
  1. Create aliasing.py with the starter code. This is the most important 15 minutes of the week โ€” go slowly and predict before every print.
  2. Section 1: a and b are two labels on ONE list. Confirm both names see the append. Then check a is b (True) versus the copied c: a == c (True) but a is c (False) โ€” same contents, different shelves.
  3. Section 2: the function-mutates-argument trap. The caller's list changed even though the function never returned anything. Write one sentence: why? (Hint: the parameter is another label on the same shelf.)
  4. Section 3: shallow copy โ€” the outer list was copied, the inner list is still shared. Sketch the two shelves on paper with an arrow to the shared inner list; this diagram IS the mental model.
  5. Fix the function in section 2 so it does NOT mutate its input: make a copy inside, or better, build and return a new list. Professional default: functions don't surprise their callers.
๐Ÿ python โ€” editable, runs in your browser
Ctrl/โŒ˜+Enter runs ยท Tab indents ยท numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)
guided 3

Dicts, sets & comprehensions in anger

15 min
  1. Create lookup.py with the starter code. Section 1 builds the classic word-frequency counter โ€” the single most reused dict pattern in this program (it returns in Day 23's hashing patterns and Day 96's tokenizer lab).
  2. Trace the .get(word, 0) + 1 line by hand for the first three words, writing the dict's state after each. This trace is the lesson.
  3. Section 2: sets โ€” dedupe the word list and test membership. Add a check: which words appear more than once? (Every word whose count is > 1.)
  4. Section 3: comprehensions. Rewrite your squares loop from exercise 1 as a comprehension, then build a dict comprehension mapping each word to its length, then filter: words longer than 3 letters.
  5. In a final comment, answer: for looking up a user's age by name, why is a dict the right shelf and a list of pairs the wrong one?
๐Ÿ python โ€” editable, runs in your browser
Ctrl/โŒ˜+Enter runs ยท Tab indents ยท numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)

On your own

The gradebook

20 min

Build gradebook.py from a blank file.

Goal: start from grades = {"ada": [92, 88, 99], "grace": [85, 91, 78], "alan": [70, 95, 88]}. Write three functions: average(scores) returns the mean of a list; report(grades) returns a NEW dict mapping each name to their average (dict comprehension encouraged); top_student(grades) returns the name with the highest average. Print a formatted line per student plus a winner line.

Constraints: no function may mutate the grades dict; averages computed with sum() and len(), not hand-typed; use .items() for iteration.

Hints (only if stuck): top_student can loop over report(grades).items() keeping a best-so-far name and score โ€” the same keep-the-best shape as Day 2's guessing game logic.

Ship before you stop

Study-log data model

Design the data structure your task tracker (Day 7) will be built on. Create studylog.py holding a list of dicts, one per completed day so far, e.g. {"day": 1, "title": "Your Machine, Your Map", "minutes": 120, "topics": ["setup", "repl"]} โ€” fill in your real Days 1โ€“3, estimating minutes honestly. Write functions: add_day(log, day, title, minutes, topics) (appends and returns the log), total_minutes(log), find_day(log, day_number) (returns the dict or None), and all_topics(log) (returns a sorted list of unique topics across all days โ€” a set does the dedupe). Demo all four under a main guard. This list-of-dicts shape is exactly how you'll hold tasks on Day 7, rows from a database on Day 36, and chat messages on Day 106.

Rubric โ€” check what you completed (0/5)

Common mistakes & misconceptions

  • Writing b = a and believing you copied the list. You copied the LABEL; both names point at one object. Use .copy(), a[:], or list(a) โ€” and remember even those are shallow.
  • Using x = x.sort() or x = x.append(3). Mutation methods return None, so x becomes None. Either mutate (x.sort()) or rebuild (x = sorted(x)) โ€” never both.
  • Reaching for grades["bob"] when the key might be absent, then crashing with KeyError. Use .get(key, default) when missing is normal; use [] when missing is a bug you WANT to hear about.
  • Membership-testing a huge list (x in big_list) inside a loop. Lists scan every element; sets and dicts jump straight there. This becomes the O(nยฒ)-vs-O(n) story of Day 22.
  • Mutating a list while looping over it (removing items mid-iteration skips elements). Loop over a copy, or build a new filtered list with a comprehension.
  • Using a list as a dict key. Keys must be immutable (hashable) โ€” use a tuple instead. This is WHY tuples exist alongside lists.
Knowledge check

Q1. a = [1, 2]; b = a; b.append(3). What is a?

Q2. You need "have we already processed this ID?" checks on millions of IDs. Best structure?

Q3. What does nums[1:3] return for nums = [5, 6, 7, 8]?

Go deeper โ€” curated resources

docsPython Tutorial โ€” Data Structures (lists, sets, dicts, comprehensions) โ†—30 minbookAutomate the Boring Stuff โ€” Ch. 4: Lists (includes references/aliasing) โ†—30 minbookAutomate the Boring Stuff โ€” Ch. 5: Dictionaries โ†—25 min
If you have a third hour
Done means
  • All three guided scripts run with written predictions checked against reality
  • The shallow-copy diagram sketched and the mutating function fixed
  • Gradebook functions work without mutating their input
  • studylog.py passes all five rubric checks
  • Quiz โ‰ฅ 2/3 (redo the aliasing lab if you missed question 1)
How this connects

โ† Back: Day 2 taught that rebinding a label never touches the old box; today added the twist โ€” MUTATING a shared box changes it for every label. Day 3's "functions shouldn't surprise callers" rule got teeth: passing a list passes a label.

Forward โ†’: This list-of-dicts model IS Day 7's task tracker, Day 36's database rows, and Day 106's chat messages. The set-vs-list membership gap becomes Day 22's central example and Day 23's hashing lesson. Shallow-vs-deep copying returns when you handle nested API payloads on Day 41.

Unlocks: D5 Strings, Files & Errors ยท D7 Week 1 Checkpoint: CLI Task Tracker ยท D9 Object-Oriented Python I ยท D10 Object-Oriented Python II