Idiomatic iteration — from concise syntax to memory-efficient pipelines
Comprehensions are the most visible marker of Python fluency — any code review in a Python shop will flag a for loop building a list when a comprehension would do. Generators go further: they're the idiomatic way to process large datasets without loading everything into memory, which matters enormously in production data pipelines.
Understanding the memory difference between a list comprehension and a generator expression is a proxy for whether you think about memory at all — a distinction worth internalising in any data-heavy work.
A list comprehension builds the entire result upfront and holds it in memory. A generator produces one item at a time, pausing between — it uses O(1) memory regardless of the number of items. The syntax is nearly identical: square brackets vs parentheses.
Think of a generator as a recipe, not a meal. The recipe doesn't cook all the food at once — it gives instructions you follow one step at a time. Only when you ask for the next item does it compute it.
A comprehension is a concise way to build a collection from an iterable in one line.
Comprehensions build collections inline in a single expression. List, dict, and set forms all follow the same [expr for item in iterable if condition] pattern.
A generator produces values on demand rather than building the full result upfront — O(1) memory regardless of input size. The yield keyword turns any function into a generator.
yield turns a function into a generator. Each next() call runs up to the next yield, pauses, and returns the yielded value. Local state is preserved between yields.
yield from delegates to a sub-generator, forwarding all values through — cleaner than a manual for loop when composing generators.