Reading — step 1 of 4
Learn
Generator Expressions
You already know list comprehensions. A generator expression looks almost identical — swap the square brackets for parentheses — but that one-character change flips the execution model. A list comprehension is eager: it computes every value right now and stores them all in memory. A generator expression is lazy: it builds a tiny generator object (the same kind you met with yield in the last lesson) that computes each value only when something asks for it.
The list costs memory proportional to its length. The generator expression costs a constant couple hundred bytes whether the range is one thousand or one billion — because it stores the recipe, not the results.
The idiom: feed aggregators directly
The killer use case is piping values straight into a function that consumes an iterable — sum, max, min, any, all, sorted, str.join:
Note there is no doubled parenthesis: when the generator expression is the sole argument, the call's own parentheses are enough. With a second argument you must wrap it yourself — sum((x for x in data), 0) — because sum(x for x in data, 0) is a straight SyntaxError ("Generator expression must be parenthesized").
any and all fed by a generator expression also short-circuit: the moment any sees a truthy value it stops pulling, and the remaining values are never computed at all. A list comprehension would have computed every one of them first.
The traps
One-shot consumption. Like every generator, a generator expression is exhausted after one pass:
That silent 0 is the nasty part — no exception tells you the generator was spent. If you need two passes, rebuild the expression or use a list.
Late name lookup. Only the outermost iterable is evaluated immediately; the body runs when the generator is consumed — including reads of outside variables:
No len, no indexing. len(g) and g[0] raise TypeError. If you need the count, random access, or repeated iteration, that is precisely when a list comprehension is the right tool. Lazy is not automatically better — it wins when you consume once and the data is large.
Your exercise
Read an integer N, then print the sum of squares from 1 to N inclusive, computed with a generator expression inside sum(...). The mistake the grader will catch is the off-by-one: range(1, n) stops at n - 1, so for input 5 you would print 30 while the grader expects exactly 55. Use range(1, n + 1), and print only the number — stdout is compared character-for-character.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…