Using next() on generator function

Question:

I have this generator function:-

def gen():
    for i in range(3):
        yield i*i

Now when I am calling next() on gen(), it is giving the first element each time.

>>> next(gen())
0
>>> next(gen())
0

But when I use that in a for loop, it works as expected:

>>> for i in gen():
...     print(i)
... 
0
1
4

Can someone explain the cause of this effect and the concept that I am missing here?

Asked By: Vicrobot

||

Answers:

Each time you call the function it returns a generator object. And each time you call the next on it you’ll get the first item which is 0 * 0 because you’re not calling the next on same object (each time a new one). But in second case you’re looping over one generator object and it will continue to consuming the generator until it hit the StopIteration.

For a better demonstration you can create two iterator objects from your generator function and loop over them simultaneously:

In [17]: g = gen()

In [18]: k = gen()

In [19]: for i, j in zip(g, k):
    ...:     print(i, j)
    ...:     
0 0
1 1
4 4
Answered By: Mazdak

Your function returns a new generator each time you call gen().

I think the simplest way to understand is to contrast what you are doing:

>>> next(gen())
0
>>> next(gen())
0

with this:

>>> my_gen = gen()
>>> next(my_gen)
0
>>> next(my_gen)
1
>>> next(my_gen)
4
>>> next(my_gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

In this latter case, I am getting new values from the same generator.

days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
def gen(d):
    for i in d: 
        yield i 

obj = gen(days)

print(next(obj, 'Default Value')) # 'Sun'
print(next(obj, 'Default Value')) # 'Mon'


for j in obj:
    print(j)  # 'Tue' 'Wed' 'Thu' 'Fri' 'Sat'
  • In above we have already called next() two times so as we know generator function save the state of program execution so in for loop it returns the
    object from next generator object

  • But if first We use for loop then during the for loop we received or called all generated objects, so we do not have any generator object left so we will get Default value for the next() function calls

Answered By: Vivek_Kumar-DASTAN
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.