We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Under the Hood: Objects, Memory, Speed step 23 of 35
render_report: join for str, bytearray for bytes
Render a CSV report twice — once as str, once as bytes — using the
accumulation strategy that is linear unconditionally rather than the one that
is linear until someone adds a log line.
def render_report(rows: Iterable[Row]) -> str: ...
def render_bytes(rows: Iterable[Row]) -> bytes: ...
Both emit the header "name,qty,price\n" followed by one line per row,
formatted f"{name},{qty},{price:.2f}\n". render_bytes must produce exactly
render_report(rows).encode("utf-8").
render_report. The starter uses text += ... in a loop. On CPython that
is currently fast, because BINARY_OP_INPLACE_ADD_UNICODE mutates the string
in place when the next opcode is STORE_FAST and the local holds the only
reference. Both conditions are outside your control: an alias
(t = text for a debug line), an attribute target (self.buffer += ...), or
a different interpreter all disable it, and the measured penalty for the alias
case is 105x. Accumulate into a list[str] and "".join once.
render_bytes. The starter has two bugs. bytes is immutable and gets no
in-place special case at all, so blob += ... reallocates and copies every
iteration — genuinely quadratic. And it encodes as "ascii", which is a guess
about the data rather than a fact about it; one of the test rows is named
café. Use a bytearray (the FAQ’s own recommendation for bytes
accumulation) and encode as UTF-8.
solve(raw, repeat) parses raw — rows of [name, qty, price] as strings —
repeat times over, renders both forms, and returns:
{"length": int, "head": str, "tail": str, "lines": int,
"bytes_match": bool, "digest": str}
where head/tail are the first and last 40 characters and digest is the
first 16 hex characters of sha256 over the bytes rendering.
One hidden case renders 200,000 rows. Nothing asserts a duration — the harness
cannot time reliably — but a genuinely quadratic accumulation (out = out + [line],
or bytes +=) does not return inside the limit, so the scale is the test.
The reasoning is the deliverable here: you should be able to say which of
your accumulations depends on a CPython implementation detail and which does
not.
Your submission must pass mypy --strict.
Stuck?
Python reference solution
Sign in to attempt this problem and reveal the reference solution.