Skip to content

← Laziness, Iteration and Pipelines step 14 of 14

Easy Primitives

zip(strict=True) and the silent-truncation bug

zip() stops at the shortest argument and says nothing about it.

That is a data-corruption bug that no test with equal-length fixtures will ever find. Names and scores drift out of sync by one row somewhere upstream, zip silently drops the tail, the report renders, the numbers look plausible, and nobody notices for a quarter. There is no exception, no warning, and no log line — the failure mode is a smaller correct-looking answer.

strict=True (3.10) turns it into a ValueError at the point the shorter argument runs out. Make that your default for any zip over two things that are supposed to correspond. Reserve plain zip for the cases where truncation is the intent, and say so in a comment when you do.

What to write

def align(names: Sequence[str], scores: Sequence[float]) -> dict[str, float]

Pair each name with its score. On a length mismatch — in either direction — raise LengthMismatch (a ValueError subclass, provided) with the message:

length mismatch: names=<len(names)>, scores=<len(scores)>

Both numbers, always. ValueError: zip() argument 2 is shorter than argument 1 is technically accurate and useless at 3am: it does not tell you how far off you are, which is the first thing you want when deciding whether a row was dropped or a whole file was truncated.

Chain the original: raise LengthMismatch(...) from exc. The __cause__ keeps zip’s own message in the traceback, so the reader can see both the domain framing and the mechanical cause.

Duplicate names are not an error — later entries win, exactly as dict() would. Empty inputs on both sides produce an empty mapping and no error.

solve is provided: it calls align and turns a LengthMismatch into the report’s error field.

Why Sequence

len() is in the message, so the parameter must be something with a length. Annotating Iterable[str] and then calling len() on it is a type error, and “just call list() first” quietly reintroduces the materialisation this track spends its time avoiding. Pick the ABC that matches what the body actually does.

Loading visualization…