Question presented to candidate: "What is a generator in Python, how is it different from a normal function that returns a list, and when would you actually choose one? Give me a case where it matters."
What a strong answer should cover:
- A function containing
yieldis a generator function: calling it runs none of the body and returns a generator object; eachnext()runs the body up to the nextyield, hands out that value and pauses with all local state kept - A generator is an iterator (it has
__iter__returning itself and__next__), sofor,list(),sum()anditertoolsaccept it; it ends withStopIterationwhen the function returns - Lazy evaluation: values are produced only when asked for, so memory stays constant regardless of input size, the first result arrives immediately, work stops when the consumer stops (
any(),break,islice), and infinite sequences become possible - Generators replace a hand-written iterator class (no
__next__, no position bookkeeping) and compose into streaming pipelines (read, filter, transform) where each item flows through every stage before the next is read - Trade-offs: single pass, no
len()or indexing, errors surface when consumed, and for small data a list can be just as fast or faster - Generator expressions
(x for x in ...)are the one-line form;yield from,send()and coroutines build on the same machinery
Code / implementation expected: Yes β a small generator function, ideally an infinite one cut with itertools.islice, or a two-stage pipeline.