← Teacher guide

One dictionary per star

Students keep each star's turtle, speed and points together in a dictionary, loop over a list of dictionaries, and see that a new property is now one key instead of one more list kept in step.

Objects with turtles · Many things on screen · about 50 minutes · Open the student lesson

Classroom resources

Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.

Students will be able to

Timing

Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min

Before class

Read the unit primer first. A dictionary pairs keys with values: {"speed": 5, "points": 2}. star["speed"] reads the value; star["speed"] = 8 changes it. Keys are text, so they need quotes; star[speed] (the bug task) looks for a variable called speed and stops with a NameError. A list of dictionaries is a table: one row per thing. The Make task repeats last lesson's bad star so students can compare a new list with a new key.

Running the lesson

  1. Predict: read the second line from the right: work out star["points"] + 1, then store it under "points".
  2. Run: ask students to find where a star's speed is stored and where it is read.
  3. Investigate: the colour question is the lesson's point. One key, made in one place.
  4. Bug task: quotes make it text. Without them Python looks for a variable.
  5. Make: compare with last lesson's bad star. No list to keep in step.

The hard part (on purpose)

Keys are text in quotes: star["speed"], not star[speed]. Ask them to read the NameError aloud and say what Python thinks speed is.

When students get stuck

What you will seeA question to askThe fix
NameError: name 'speed' is not defined.Is the key in quotes?star["speed"], not star[speed].
KeyError: 'colour'.Was the key added to every dictionary when the stars were made?Add the key in the dictionary where each star is made, with the same spelling.
All the stars are the same colour.Where is each turtle coloured, and which value does it use?After the loop that makes them: star["turtle"].color(star["colour"]) for each star.

Answers to the checks

  1. Predict: What does it print?
    5 3. star["points"] starts at 2; the second line stores 2 + 1 back under "points". star["speed"] is still 5.
  2. Match the pieces: Match each piece with what it does.
    {"speed": 5, "points": 1} → A. a dictionary: keys paired with values; star["speed"] → B. the value stored under the key "speed"; star["points"] = 3 → D. changes the value stored under "points"; for star in stars: → C. each dictionary in the list, one at a time
  3. A new property: Every star should also remember its colour. What changes?
    One more key in the dictionary where each star is made
    Add "colour": ... where the dictionary is made, then read star["colour"] where it is needed. Nothing else can fall out of step.
  4. Spot the bug: This should print each star's speed doubled, but it stops with a NameError. Click the line that causes it.
    line 3
    Keys are text, so they need quotes: star["speed"]. Without quotes Python looks for a variable called speed, which does not exist.
  5. Where this leads: A school stores each student as a dictionary: {"name": "Ada", "year": 9}. What is a list of them?
    A table: one row per student, one column per key
    A list of dictionaries is a table, which is how most data is stored: spreadsheets, databases and the data sets in Data detective.

Solutions

One possible solution for each task. Other correct programs are fine.

Modify › Different points

from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

stars = []
for i in range(4):
    s = Turtle()
    s.shape("circle")
    s.penup()
    s.goto(-150 + i * 100, 200)
    s.setheading(270)
    stars.append({
        "turtle": s,
        "speed": random.randint(3, 7),
        "points": random.randint(1, 3),
    })

for star in stars:
    star["turtle"].color("gold")

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    for star in stars:
        star["turtle"].forward(star["speed"])
        if star["turtle"].distance(xcor(), ycor()) < 25:
            score += star["points"]
            star["turtle"].goto(random.randint(-200, 200), 200)
        if star["turtle"].ycor() < -220:
            star["turtle"].goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()

Modify › Colours

from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

colours = ["gold", "orange", "yellow"]
stars = []
for i in range(4):
    s = Turtle()
    s.shape("circle")
    s.penup()
    s.goto(-150 + i * 100, 200)
    s.setheading(270)
    stars.append({
        "turtle": s,
        "speed": random.randint(3, 7),
        "points": 1,
        "colour": colours[i % 3],
    })

for star in stars:
    star["turtle"].color(star["colour"])

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    for star in stars:
        star["turtle"].forward(star["speed"])
        if star["turtle"].distance(xcor(), ycor()) < 25:
            score += star["points"]
            star["turtle"].goto(random.randint(-200, 200), 200)
        if star["turtle"].ycor() < -220:
            star["turtle"].goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()

Make a bad star

from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

stars = []
for i in range(4):
    s = Turtle()
    s.shape("circle")
    s.penup()
    s.goto(-150 + i * 100, 200)
    s.setheading(270)
    stars.append({
        "turtle": s,
        "speed": random.randint(3, 7),
        "points": 1,
        "bad": i == 0,
    })

for star in stars:
    if star["bad"]:
        star["turtle"].color("red")
    else:
        star["turtle"].color("gold")

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    for star in stars:
        star["turtle"].forward(star["speed"])
        if star["turtle"].distance(xcor(), ycor()) < 25:
            if star["bad"]:
                score -= 3
            else:
                score += star["points"]
            star["turtle"].goto(random.randint(-200, 200), 200)
        if star["turtle"].ycor() < -220:
            star["turtle"].goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()

Stretch and support

Stretch: Add a "hits" key that counts how often each star has been caught, and make a star faster every third catch.

Support: Give students the "bad" key already in the dictionary and ask them only to change what happens when a star is caught.

Exit ticket

pet = {"name": "Rex", "legs": 4}. Write the line that changes legs to 3.

pet["legs"] = 3

What each step is for

Where it leads

Next lesson makes a Star class, so a star's values read star.speed instead of star["speed"], and later the star can do things itself. Data detective uses lists of dictionaries for real data sets.