Comet spreads the four field samples on the table. "I want a quick report," she says. "Total grams, the heaviest sample and how many are heavy."
"One loop can do all three," she adds, already reaching for the keyboard.
Wren slides his clipboard over first. "What does the evidence say after each pass?" he asks. "Trace it on paper, then we run it."
Nova projects an empty trace table with four rows. "How can I help?" she asks. "One row for each sample. Fill in the names as they change."
Comet grins and picks up a pencil. "Fine. Lead programmer, you call out the values."
A list of objects is walked like any list. Each pass, s refers to the next Sample, and the dot reaches its attributes and methods.
Python's own glossary says a list is more like an array in other languages. You will meet arrays when you read Java later in the course.
# report.py
from sample import Sample
samples = [
Sample("S01", "basalt", 42, 0, 2),
Sample("S02", "quartz", 18, 2, 4),
Sample("S03", "clay", 65, 3, 0),
Sample("S04", "mica", 7, 4, 5),
]
total = 0
heaviest = samples[0]
heavy_count = 0
for s in samples:
total += s.grams
if s.grams > heaviest.grams:
heaviest = s
if s.is_heavy():
heavy_count += 1
print("Total:", total)
print("Heaviest:", heaviest.label)
print("Heavy:", heavy_count) | Pass | s | total | heaviest | heavy_count |
|---|---|---|---|---|
| before the loop | none yet | 0 | S01 | 0 |
| 1 | S01 | 42 | S01 | 0 |
| 2 | S02 | 60 | S01 | 0 |
| 3 | S03 | 125 | S03 | 1 |
| 4 | S04 | 132 | S03 | 1 |
Total: 132 Heaviest: S03 Heavy: 1
Sometimes a search finds nothing. find_kind below returns the first sample of a kind, or None when no sample matches.
The two assert lines at the end are tests. If both pass, the last print runs.
# find_kind.py
from sample import Sample
def find_kind(samples, kind):
"""Precondition: samples is a list of Sample objects.
Postcondition: gives back the first Sample of that kind, or None."""
for s in samples:
if s.kind == kind:
return s
return None
samples = [Sample("S01", "basalt", 42), Sample("S04", "mica", 7)]
hit = find_kind(samples, "mica")
print(hit.describe())
miss = find_kind(samples, "chalk")
print(miss)
assert find_kind(samples, "basalt").grams == 42
assert find_kind(samples, "chalk") is None
print("find_kind tests passed") S04 mica 7 g at (0, 0) None find_kind tests passed
Calling a method on None is a mistake. Here miss is None, and the program asks it to describe itself:
# none_trap.py
from sample import Sample
samples = [Sample("S01", "basalt", 42)]
miss = None
for s in samples:
if s.kind == "chalk":
miss = s
print(miss.describe()) Traceback (most recent call last):
File "none_trap.py", line 9, in <module>
print(miss.describe())
^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'describe' A class bundles data and the functions that work on it. In FieldSim the crew picks a shape for each job. Choose the one that fits.
Strong tracing this week. Tomorrow is a Mission Quest with sticky notes and boxes.