Comprehensions & Generators
Concise, often faster ways to build sequences — and the lazy-evaluation alternative that avoids materializing them at all.
Comprehensions
[x*2 for x in range(10) if x % 2 == 0] builds a list in one expression instead of a loop with .append() — typically faster too, since the loop runs in C rather than interpreted Python bytecode. Dict and set comprehensions follow the same pattern: {k: v for ...}, {x for ...}.
Generators
A generator ((x for x in ...), or a function using yield) produces values lazily, one at a time, instead of building the whole sequence in memory upfront. This matters when the sequence is huge or infinite — sum(x*x for x in range(10**9)) never holds a billion-element list in memory.
The trade-off
A list comprehension can be iterated multiple times and supports indexing; a generator is single-use (once consumed, it's exhausted) and doesn't support indexing, but uses O(1) memory regardless of sequence length versus a list's O(n).
Where it matters
Processing large files or streams line-by-line, or any pipeline where you only ever need "the next value," not the whole collection at once.
