Records

Grouping related fields: a sensor reading as a record, and a list of records as a table.

F3.6Strings, lists and recordsGCSE15 min

Do this lesson in the simulator

A distance reading on its own is only a number. It becomes information when you also know which way the robot was facing and when it was taken. A record groups related values of different kinds under one name, each value in a named field. A list of records is a table: each record is a row, each field a column.

A record as a dictionary

Python's most common way to write a record is a dictionary: fields named by strings, in curly brackets:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

reading = {"heading": 0, "distance": distance(), "battery": battery()}
print(reading)
print("facing", reading["heading"], "the wall is", reading["distance"], "cm away")
reading["note"] = "first look"      # add a field
reading["heading"] = 90             # change a field
print(reading)

Run this in the simulator

A field is reached by its name in square brackets, reading["distance"], where a list would use a number. The fields hold different types here: an integer, a real, and later a string. That mix is what makes a record different from an array.

A list of records

One record per reading, collected in a list, gives a table:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

log = []
for i in range(4):
    log.append({"look": i + 1, "heading": i * 90, "distance": distance()})
    turn_right(30, angle=90)

for r in log:
    print(f"look {r['look']}: facing {r['heading']}, {r['distance']} cm")

Run this in the simulator

look heading distance
1 0 ...
2 90 ...
3 180 ...
4 270 ...

Inside an f-string that already uses double quotes, the field names go in single quotes: r['heading'].

Searching a table of records

The patterns you know work on records: go through the list and look at one field:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

log = [
    {"heading": 0, "distance": 31.0},
    {"heading": 90, "distance": 51.0},
    {"heading": 180, "distance": 15.0},
    {"heading": 270, "distance": 31.0},
]
closest = log[0]
for r in log:
    if r["distance"] < closest["distance"]:
        closest = r
print("closest wall is at heading", closest["heading"], closest["distance"], "cm")

for r in log:
    if r["distance"] > 30:
        print("room to drive at heading", r["heading"])

Run this in the simulator

Keeping the whole record as closest, not only the distance, means the heading comes with it for free.

Records as their own type

A dictionary does not stop you misspelling a field name. For bigger programs Python can define a record type with fixed fields, a dataclass:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

from dataclasses import dataclass

@dataclass
class Reading:
    heading: int
    distance: float

r = Reading(90, distance())
print(r)
print(r.heading, r.distance)

Run this in the simulator

The fields are listed once, with their types, and reached with a dot. This is close to how exam pseudo-code writes records. Either form is fine for this module.

Task: reading records

The robot is boxed in on three sides. Look in four directions, 90 degrees apart, storing each look as a record with the fields heading and distance in a list. Then print one line per record as heading 0: 31.0 cm, and finally print closest heading: <heading> for the record with the smallest distance.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

log = []
for i in range(4):
    turn_right(30, angle=90)

Challenges

  1. Add a time field to each record using clock().
  2. Print the log as a table, with the headings lined up using f-string widths like {r['distance']:6}.
  3. Store three names and scores as records and print the name with the highest score.