← Back to course
Python 11-12 / Week 02 / Wednesday
3/6
Week 02 · Classes and Objects

Wednesday

Sim Lab: sample.py
// A class is a blueprint, and each object keeps its own state
⏱ about 30 min

Wednesday: Sim Lab: sample.py

Today the crew writes the first real FieldSim file. Comet has sketched the Sample class in her notebook: five attributes and two methods.

"describe() gives one line about a sample," she says. "is_heavy() says True for 50 grams or more. Then the four field samples become objects!"

Wren checks the sketch against last week's dict prototype. "What does the evidence say?" he asks. "The describe() lines must match the old ones exactly, or we lose our tests."

Nova splits the wall into four stages. "How can I help?" she asks. "Type a stage, predict, run, then move on."

Comet hands you the keyboard. "Lead programmer, stage one."

Sim Lab: the Sample class

sample.py holds only the class. A second file, field_log.py, makes the four field samples and prints them.

Both files go in your fieldsim folder, so field_log.py can import from sample.py. The samples are made-up data from the FieldSim story.

  1. Stage 1: type the class and its constructor in sample.py.
  2. Stage 2: add the methods describe() and is_heavy().
  3. Stage 3: write field_log.py to make and print the four samples.
  4. Stage 4: change field_log.py once, then break sample.py on purpose and fix it.

Stage 1: the constructor

# sample.py
# A Sample is one rock or soil token the rover picks up.


class Sample:
    """One sample token from the test field."""

    def __init__(self, label, kind, grams, row=0, col=0):
        self.label = label
        self.kind = kind
        self.grams = grams
        self.row = row
        self.col = col

Run Module on sample.py shows nothing at all. The file only defines the class; nothing calls it yet.

Stage 2: two methods

Add describe() and is_heavy() under __init__. This is the whole of sample.py.

Both methods use self to reach the attributes of the object they were called on.

# sample.py
# A Sample is one rock or soil token the rover picks up.


class Sample:
    """One sample token from the test field."""

    def __init__(self, label, kind, grams, row=0, col=0):
        self.label = label
        self.kind = kind
        self.grams = grams
        self.row = row
        self.col = col

    def describe(self):
        return f"{self.label} {self.kind} {self.grams} g at ({self.row}, {self.col})"

    def is_heavy(self):
        return self.grams >= 50

Stage 3: field_log.py

# field_log.py
# The four field samples as Sample objects (made-up FieldSim data).
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),
]

for s in samples:
    print(s.describe())
PREDICT STAGE 3
  • Read the question.
  • Tap your answer.
What is the last line field_log.py shows?
Do these lines match last week's dict prototype?
S01 basalt 42 g at (0, 2)
S02 quartz 18 g at (2, 4)
S03 clay 65 g at (3, 0)
S04 mica 7 g at (4, 5)

Stage 4: one change, one break

The change: add a second loop at the end of field_log.py that names every heavy sample.

# field_log.py
# The four field samples as Sample objects (made-up FieldSim data).
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),
]

for s in samples:
    print(s.describe())

for s in samples:
    if s.is_heavy():
        print(s.label, "is heavy")
PREDICT THE CHANGE
  • Read the question.
  • Tap your answer.
How many is heavy lines appear?

The break: in sample.py, take self out of the describe line, so it reads def describe():. Save it and run field_log.py.

# field_log.py
# The four field samples as Sample objects (made-up FieldSim data).
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),
]

for s in samples:
    print(s.describe())
Traceback (most recent call last):
  File "field_log.py", line 13, in <module>
    print(s.describe())
          ~~~~~~~~~~^^
TypeError: Sample.describe() takes 0 positional arguments but 1 was given
READ THE TYPEERROR
  • Read the question.
  • Tap your answer.
The message says one argument was given. Which object was it?
What is the fix?
At your computer
1. Stage 1: type the first 13 lines of sample.py and save it in fieldsim. Run it and check that nothing appears.
2. Stage 2: add describe() and is_heavy(). Save and run it again.
3. Stage 3: open a new file, type field_log.py and save it in fieldsim. Predict the last line, then run it.
4. Stage 4: add the heavy loop to field_log.py and run it.
5. Take self out of def describe(self): in sample.py and save. Run field_log.py and read the TypeError.
6. Put self back, save sample.py and run field_log.py once more.

sample.py is now a real FieldSim file, and it stays in your folder for the rest of the course. Tomorrow: what happens when two objects look alike?

← Tuesday