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

Dave Angel davea at ieee.org
Sat Apr 4 17:41:54 CEST 2009


grocery_stocker wrote:
> Given the following
>
> [cdalten at 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.
>   
>>>> def counter():
>>>>         
> ...   mylist = range(3)
> ...   for i in mylist:
> ...      yield i*i
> ...
>   
>>>> counter
>>>>         
> <function counter at 0xb7e79e64>
>   
>>>> gen = counter()
>>>> gen
>>>>         
> <generator object at 0xb7e7c1cc>
>   
>>>> while True:
>>>>         
> ...    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
>   
>>>> try:
>>>>         
> ...    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.





More information about the Python-list mailing list