We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Memory, Copies and Slow Code step 24 of 38
Build a Report as Text and UTF-8 Bytes
Your shop exports its stock as a small comma-separated report. Write the
two functions that render it, one as text and one as UTF-8 bytes. The
starter builds both with += in a loop. The bytes version copies the whole
report for every line, so it slows down badly on large reports, and its
ASCII encoding fails on a name like café. The text version is fast only
because of the CPython shortcut that the article describes.
rows = [Row("widget", 3, 1.5), Row("café", 1, 9.999)]
assert render_report(rows) == "name,qty,price\nwidget,3,1.50\ncafé,1,10.00\n"
assert render_bytes(rows) == render_report(rows).encode("utf-8")
What to write
render_report(rows: Iterable[Row]) -> strappends the lines to alist[str]and joins them once.render_bytes(rows: Iterable[Row]) -> bytesadds each UTF-8 encoded line to abytearray, then converts it tobytesonce at the end.
Both use the same format:
- Start with
HEADER, which is"name,qty,price\n", even when there are no rows. - Then write one line per row, in input order, formatted exactly as
f"{row.name},{row.qty},{row.price:.2f}\n". Every line ends in a newline. - Write names as they are, with no quoting or escaping. This is a simple comma-separated format, not a full CSV writer.
- Format prices with
.2f, so9.999becomes10.00. Don't round them any other way. Python stores a float such as12.005as a value slightly off from what you typed, and.2frounds the stored value. - For the same rows,
render_bytesreturns exactly whatrender_report(rows).encode("utf-8")returns.
Each function must work on input that can be read only once, such as a
generator. Loop over rows once, and give each renderer its own input.
What the driver reports
Keep Row, HEADER, parse and solve as they are. parse(raw, repeat)
turns each [name, qty, price] row of strings into a Row, and repeats
the whole list repeat times. A repeat of zero or less gives no rows, and
the header still appears once. solve renders the same rows both ways and
returns:
| Key | Meaning |
|---|---|
length |
len(text), which counts characters, not bytes |
head |
the first 40 characters of the text, or all of it if shorter |
tail |
the last 40 characters of the text, or all of it if shorter |
lines |
the number of newlines in the text, including the header's |
bytes_match |
whether the bytes equal text.encode("utf-8") |
digest |
the first 16 hex characters of the SHA-256 of the bytes |
The largest test renders 200,000 rows. Your submission must pass
mypy --strict.
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.