1

I am trying to understand the flow of control while defining a generator.

def countdown(num)
    print('Starting')
    while num > 0:
        yield num
          num -= 1
val = countdown(5)

when I call next(val), Starting gets printed followed by the number 5 but in the subsequent calls only the number gets printed. why am I not seeing Starting? and why does it show an error when I call next(val) more than 5 times? Any help in understanding the control flow will be much appreciated

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Kai
  • 122
  • 6
  • Welcome to SO. This isn't a help forum or discussion forum. Please take the time to read [ask] and the other links found on that page. When a generator is *finished* it raises a `StopIteration` Exception - pretty sure that is in the documentation. – wwii Jun 26 '19 at 02:24

3 Answers3

2

When calling next() the first time, execution begins at the start of the function body and continues until the next yield statement where the value to the right of the statement is returned.

Subsequent calls to next() continue from the yield statement to the end of the function, and loop around and continue from the start of the while loop until another yield is called.

If yield is not called (which in your case means that you don’t go into the while function because num <= 0) a StopIteration exception will be raised.

TheLastCoder
  • 610
  • 2
  • 6
  • 15
1

Move Starting inside the while block:

def countdown(num):
    while num > 0:
        print('Starting')
        num -= 1
        yield num

val = countdown(5)
for i in range(5):
    print(next(val))

Output:

Starting
4
Starting
3
Starting
2
Starting
1
Starting
0
wjandrea
  • 28,235
  • 9
  • 60
  • 81
arajshree
  • 626
  • 4
  • 13
1

Well, currently you're simply only printing Starting once, and since it isn't yielded, it comes with the first yield. Why shouldn't it throw an error after it reaches 0? it should, since the yield repentance will stop, and next only works if there are still gonna be more yield. To tweak it a little so that it doesn't print Starting with only 5, but as well as the other numbers, and doesn't raise any errors, do:

def countdown(num):
    while num > 0:
        print('Starting')
        yield num
        num -= 1
    while True:
        yield 'The number reached zero, it stopped'
val = countdown(5)

Testing with:

for i in range(10):
    print(next(val))

Gives:

Starting
5
Starting
4
Starting
3
Starting
2
Starting
1
The number reached zero, it stopped
The number reached zero, it stopped
The number reached zero, it stopped
The number reached zero, it stopped
The number reached zero, it stopped
U13-Forward
  • 69,221
  • 14
  • 89
  • 114