Why doesn't StopIteration get caught in the following code?

  • Thread starter grocery_stocker
  • Start date
G

grocery_stocker

Given the following

[cdalten@localhost ~]$ python
Python 2.4.3 (#1, Oct 1 2006, 18:00:19)
[GCC 4.1.1 20060928 (Red Hat 4.1.1-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information..... mylist = range(3)
.... for i in mylist:
.... yield i*i
........ i = gen.next()
.... print i
....
0
1
4
Traceback (most recent call last):
File "<stdin>", line 2, in ?
StopIteration


I thought the 'for' in counter() was supposed to catch StopIteration.
Ie, I thought that something like

.... for i in mylist:
.... yield i*i

Got translated to something like.... while True:
.... do some stuff
.... except StopIteration:
.... pass
....
 
D

Dave Angel

grocery_stocker said:
Given the following

[cdalten@localhost ~]$ python
Python 2.4.3 (#1, Oct 1 2006, 18:00:19)
[GCC 4.1.1 20060928 (Red Hat 4.1.1-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
... mylist = range(3)
... for i in mylist:
... yield i*i
...
... i = gen.next()
... print i
...
0
1
4
Traceback (most recent call last):
File "<stdin>", line 2, in ?
StopIteration


I thought the 'for' in counter() was supposed to catch StopIteration.
Ie, I thought that something like

... for i in mylist:
... yield i*i

Got translated to something like
... while True:
... do some stuff
... except StopIteration:
... pass
...
There are two separate StopIteration's here. The for statement you
describe will indeed catch the StopIteration from the list's iterator.

But that for statement is inside a generator function, and the generator
function throws a StopIteration when it returns (as opposed to when it
yields). If you had used that generator inside another for statement,
it would have worked as you expect. But when you call nest()
explicitly, you have to be prepared for the exception. Clearly, the
while True loop cannot go forever, when your generator is finite.
 
T

Terry Reedy

grocery_stocker wrote:
....
... i = gen.next()
... print i
...
0
1
4
Traceback (most recent call last):
File "<stdin>", line 2, in ?
StopIteration

If you had written

for item in gen: print(i)

then StopIteration from gen would be caught.

One expansion of a for loop is (in the above case)

it = iter(gen) # not needed here, but is for general iterables
try:
while True:
i = it.next()
print(i) # or whatever the loop body is
except StopIteration:
pass

In other words, 'for i in iterable' expands to several lines of
boilerplate code. It is very useful syntactic sugar.

You left out the try..except part.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,965
Messages
2,570,148
Members
46,710
Latest member
FredricRen

Latest Threads

Top