Question presented to candidate: "People use 'iterable' and 'iterator' as if they meant the same thing. What exactly is the difference in Python? If I give you a list and a generator, which is which, and why can I loop over the list twice but not the generator?"
What a strong answer should cover:
- An iterable is anything
iter()can turn into an iterator: it defines__iter__(or the older__getitem__sequence protocol). An iterator is the object that actually produces values: it defines__next__, plus an__iter__that returns itself next()on an exhausted iterator raisesStopIteration; iterators are single-pass and never rewind- A container such as a list hands out a new, independent iterator on every
iter()call, so it can be looped over many times; a generator,map,zip,enumerateor a file object is its own iterator, so it is consumed once - Every iterator is iterable, but not every iterable is an iterator (
isinstance(x, Iterator)vsIterable, and whyiter(x) is xis the quick test) - Practical consequences:
in,any(),sum()partially or fully consume an iterator; the right design is an iterable class whose__iter__returns a fresh iterator (often a generator) - The reliable "is it iterable?" check is calling
iter()and catchingTypeError, becausecollections.abc.Iterablemisses__getitem__-only classes
Code / implementation expected: Optional β a small class pair (container plus iterator) or a demonstration that list(gen) is empty the second time.