We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Everyday Standard Library Tools step 29 of 55
Cache a Report Total Until You Clear It
The starter caches each report's total in a dictionary on the class, with the
report as the key. That dictionary keeps every report alive after the caller
has finished with it. Rewrite Report to store the total on the instance with
cached_property.
report = Report([1, 2, 3])
report.total # 6, computed
report.rows.append(5)
report.total # 6, still cached
report.invalidate()
report.total # 11, computed again
report.computations # 2
What to write
Fill in Report(rows):
- Copy the input into
self.rows, so that appending to it does not change the caller's list. - Start
self.computationsat 0. - Make
totalacached_property. Each time its method runs, add 1 tocomputationsand returnsum(self.rows). The decorator caches a total of 0 like any other value. - Give
Reportaninvalidate()method that removes a stored total. Calling it before the first read, or twice in a row, must not raise and must not compute a total. - Remove the class-level dictionary. Keep
Reporta normal class without__slots__, becausecached_propertyneeds the instance's__dict__.
What the report shows
Keep solve as it is. It creates one Report from rows and runs each
operation in script, in order:
| Operation | Effect |
|---|---|
read |
Appends report.total to reads |
invalidate |
Calls report.invalidate() |
add |
Appends 5 to report.rows, without invalidating |
Any other operation raises ValueError. Then solve saves computations,
makes a weak reference to the report, deletes its own reference, and runs
gc.collect(). A weak reference lets you check whether an object still exists
without keeping it alive. The result is:
{"reads": reads, "computations": computations, "leaked": tracker() is not None}
The tests expect leaked to be False. With the starter it is True whenever
a total is still cached when the script ends, because the class-level
dictionary then still holds the report.
For rows=[1, 2, 3] and script=["read", "add", "read", "invalidate", "read"],
the result is {"reads": [6, 6, 11], "computations": 2, "leaked": False}.
Edge cases
- Empty
rowsgive a total of 0. - An empty script gives
reads == []andcomputations == 0. - Invalidating does not reset
computations.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.