Avoid Multiple Next () Statement in Python Generator

Question:

I’m using a library that returns a generator. Is there a way to start at a particular iteration without using multiple next () statement?

In a simple for loop, I could do the following.

array = [2, 5, 1, 4, 3]

for i in array [2:]:
    # do something

In a generator, I couldn’t do as shown above. Instead I’ll have to use multiple next () statements to start at the 3rd index. When attempting to do the same as the for loop, I get an error that said, “generator is not scriptable.”

Asked By: dreamzboy

||

Answers:

itertools.islice does this, but in reality, it’s just invoking next for you over and over (though at the C layer in CPython, so it’s faster than doing it manually).

for i in itertools.islice(mygenerator, 2, None):
    # do something

Or to avoid per-element overhead for iterating the remainder of the generator, you can consume the elements with islice, then iterate the generator directly:

# Consumes up to two items from any iterator; note: MUST be iterator already
# for this to be helpful; if it's not, you need to start with:
# mygenerator = iter(mynoniterator)
next(itertools.islice(mygenerator, 2, 2), None)

for i in mygenerator:  # Iterate directly after consuming skipped elements
    # do something
Answered By: ShadowRanger

Yes, you can use itertools.islice() , which can slice the generator as you want –

>>> def a():
...     for i in range(10):
...             yield i
...
>>>
>>>
>>> x = a()
>>> import itertools
>>> for i in itertools.islice(x, 2, None):
...     print(i)
...
2
3
4
5
6
7
8
9

Please note, though you are not manually doing the multiple next() , it is being internally done by islice() . You cannot reach at the required index until you iterate till it (islice just does that for you , instead of you have to write multiple next() , etc).


The signature of itertools.islice is –

itertools.islice(iterable, stop)
itertools.islice(iterable, start, stop[, step])

The first argument is always the iterable, then if you pass in only 2 arguments, second argument is interpreted as the stop index (exclusive, meaning it does not return the stop index element).

If there are 3 or 4 arguments to it , second argument is treated as the start index (index) , third argument as the stop (exclusive) , and if fourth argument is specified its treated as the step value.

Answered By: Anand S Kumar