Wren has written three tests for describe() on his clipboard. Each one names a sample and the exact line it should give back.
"These are the promises describe() makes," he says. "If one fails, the evidence tells us at once."
Comet frowns at the function. "But what does describe() need before it can keep those promises?" she asks. "A dict with all five keys, I bet."
Nova projects the function with two short notes above its code. "How can I help?" she asks. "Write the need and the promise into the docstring, so the next reader sees them."
Comet hands you the pencil. "Lead programmer, you write the notes. Then we trace."
Comments are for you and for other programmers, so they can understand the code and what it does.
A precondition is a condition that must be true just before a function runs, so that it works as expected.
A postcondition is a condition that is always true after it runs. A docstring right under def is a good place to write both.
# test_describe.py
# Three tests for describe(), the dict version from Wednesday.
def describe(sample):
"""Give back one line about a sample.
Precondition: sample is a dict with the keys label, kind, grams, row and col.
Postcondition: the result is a string like "S01 basalt 42 g at (0, 2)".
"""
return (f"{sample['label']} {sample['kind']} {sample['grams']} g "
f"at ({sample['row']}, {sample['col']})")
s01 = {"label": "S01", "kind": "basalt", "grams": 42, "row": 0, "col": 2}
s04 = {"label": "S04", "kind": "mica", "grams": 7, "row": 4, "col": 5}
assert describe(s01) == "S01 basalt 42 g at (0, 2)"
assert describe(s04) == "S04 mica 7 g at (4, 5)"
assert describe(s04).startswith("S04")
print("All 3 describe tests passed") All 3 describe tests passed
Here someone has changed describe() and dropped the g after the grams. Run the same tests on it.
# test_describe.py, with a changed describe()
def describe(sample):
return (f"{sample['label']} {sample['kind']} {sample['grams']} "
f"at ({sample['row']}, {sample['col']})")
s01 = {"label": "S01", "kind": "basalt", "grams": 42, "row": 0, "col": 2}
s04 = {"label": "S04", "kind": "mica", "grams": 7, "row": 4, "col": 5}
assert describe(s01) == "S01 basalt 42 g at (0, 2)"
assert describe(s04) == "S04 mica 7 g at (4, 5)"
assert describe(s04).startswith("S04")
print("All 3 describe tests passed") Traceback (most recent call last):
File "test_describe.py", line 9, in <module>
assert describe(s01) == "S01 basalt 42 g at (0, 2)"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError Trace each program on paper first. Then choose the output.
# trace_drill.py
grams = [42, 18, 65, 7]
score = 0
for g in grams:
if g >= 50:
score += 2
elif g < 10:
score -= 1
print(score) # halving.py
n = 65
steps = 0
while n > 10:
n = n // 2
steps += 1
print(n, steps) | Step | n | steps | n > 10? |
|---|---|---|---|
| start | 65 | 0 | True |
| pass 1 | 32 | 1 | True |
| pass 2 | 16 | 2 | True |
| pass 3 | 8 | 3 | False, so the loop stops |
8 3
Five days, five tools, lead programmer. Tomorrow is Mission Quest: you and a family member become the computer.