2 ms·
Python iterators: wat
- zephyrfalcon 8y agoI had to stare at this for a while before I figured it out. `works` and `notworks` are both generators. They take an iterator (over a list) and take two elements from it, then yield this. So when given [1,2,3,4] you would expect to get back, [1,2], then [3,4], then StopIteration is raised. `works` uses a list comprehension. It gets [1,2], [3,4], then there are fewer than two elements left, so StopIteration is raised, the toplevel call wraps the results in a list, and returns [[1,2], [3,4]]. `notworks` uses list() with another generator. This does look like it would have the same behavior as the listcomp, but it does not. When we turn an iterator/generator into a list, and the generator raises StopIteration, list() will return a list of all the values produced so far. So it produces: [1,2], [3,4], then [5], then endlessly []. You can inspect the behavior by looping over the generator calls, e.g. for x in works(iter([1,2,3,4,5])): print(x) tl;dr: In `works`, the StopIteration is handled by `works` itself, while in `notworks` it is intercepted by the call to list(), rather than by `notworks`. This causes the difference in behavior.