Considering this example:
from itertools import cycle
def foo():
for i in range(3):
yield i
c = cycle(foo())
next(c) # -> 0
next(c) # -> 1
next(c) # -> 2 [StopIteration should be thrown here normally]
next(c) # -> 0
...
How does cycle
prevent the generator from exciting via a StopIteration
? I thought a generator could only be executed once, since the generator only returns its current value and moves on.
Is cycle
simply re-creating the generator when StopIteration
is thrown? Could this become a problem (inefficiency) when I iterate over for example large numpy arrays?
Secondary question: is this a "pythonic" way of cycling large data sets with iterators/generators? Or should I transfer the cycling logic directly to the generator itself (like defining indexes and using a while loop with resetting indexes)?
My intention is to cycle through large data sets (mostly numpy array; >100.000 entries) efficiently.
How does
cycle
prevent the generator from exciting via aStopIteration
?
It doesn't. The generator reaches its end and exits with a StopIteration
as normal. cycle
stores the generator's output, and when cycle
sees the StopIteration
, it switches to producing items from its stored history of what the generator produced.