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.
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.
Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min
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.
Keys are text in quotes: star["speed"], not star[speed]. Ask them to read the NameError aloud and say what Python thinks speed is.
| What you will see | A question to ask | The 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. |
One possible solution for each task. Other correct programs are fine.
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()
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()
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: 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.
pet = {"name": "Rex", "legs": 4}. Write the line that changes legs to 3.
pet["legs"] = 3
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.