Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > iterators: class vs generator

Reply
Thread Tools

iterators: class vs generator

 
 
Clark C. Evans
Guest
Posts: n/a
 
      08-24-2004
There is an interesting difference between how exceptions are handled
between iterators constructed from a class, and iterators constructed
from a generator. The following are "mostly equivalent":

class iterable_via_class:
def __iter__(self):
self._next = self._one
return self
def next(self):
return self._next()
def _one(self):
self._next = self._two
return "one"
def _two(self):
self._next = self._stop
return "two"
def _stop(self):
raise StopIteration()

def iterable_via_generator():
yield "one"
yield "two"

print "\nclass:"
for x in iterable_via_class():
print x

print "\ngenerator:"
for x in iterable_via_generator():
print x

However, when exceptions are involved, behavior can be different:

class iterable_via_class:
def __iter__(self):
self._next = self._one
return self
def next(self):
return self._next()
def _one(self):
self._next = self._raise
return "one"
def _raise(self):
self._next = self._two
raise Exception()
def _two(self):
self._next = self._stop
return "two"
def _stop(self):
raise StopIteration()

def iterable_via_generator():
yield "one"
raise Exception()
yield "two"

def test(itergen):
it = iter(itergen())
print it.next()
try:
ignore = it.next()
except:
pass
print it.next()

print "\nclass:"
test(iterablex)
print "\ngenerator:"
test(iterable)
 
Reply With Quote
 
 
 
 
Michael Hudson
Guest
Posts: n/a
 
      08-25-2004
"Clark C. Evans" <(E-Mail Removed)> writes:

> There is an interesting difference between how exceptions are handled
> between iterators constructed from a class, and iterators constructed
> from a generator. The following are "mostly equivalent":


[...]

> However, when exceptions are involved, behavior can be different:


(It would have been nice if you'd explained what the differences were
in your post, and given that you'd didn't if you'd made sure the
examples were correct -- got a NameError for iterable...)

Here's a better illustration:

>>> def iterable_via_generator():

.... yield "one"
.... raise Exception()
.... yield "two"
....
>>> i = iterable_via_generator()
>>> i.next()

'one'
>>> i.next()

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in iterable_via_generator
Exception
>>> i.next()

Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration

I agree this is surprising. I am vaguely aware of some effort being
put in to make generators "stick", i.e. this doesn't surprise me so
much:

>>> def g():

.... yield 1
.... return
.... yield 2
....
>>> i = g()
>>> i.next()

1
>>> i.next()

Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration
>>> i.next()

Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration

I'd guess the behaviour you've noticed is an unintended consequence of
this. I'd also be willing to be persuaded that it's a bug, although
others might disagree, dunno. File an issue, anyway?

Cheers,
mwh

--
I would hereby duly point you at the website for the current pedal
powered submarine world underwater speed record, except I've lost
the URL. -- Callas, cam.misc
 
Reply With Quote
 
 
 
 
Andrew Durdin
Guest
Posts: n/a
 
      08-25-2004
On Wed, 25 Aug 2004 11:24:41 GMT, Michael Hudson <(E-Mail Removed)> wrote:
>
> Here's a better illustration:
>
> >>> def iterable_via_generator():

> .... yield "one"
> .... raise Exception()
> .... yield "two"
> ....
> >>> i = iterable_via_generator()
> >>> i.next()

> 'one'
> >>> i.next()

> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File "<stdin>", line 3, in iterable_via_generator
> Exception
> >>> i.next()

> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> StopIteration



This is correct behaviour according to PEP 255:
"""
If an unhandled exception-- including, but not limited to,
StopIteration --is raised by, or passes through, a generator function,
then the exception is passed on to the caller in the usual way, and
subsequent attempts to resume the generator function raise
StopIteration. In other words, an unhandled exception terminates a
generator's useful life.
"""
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Problems with email.Generator.Generator Chris Withers Python 20 09-12-2006 11:13 AM
UART with fractional baudrate generator ? Or fractional baudrate generator alone Martin Maurer VHDL 3 04-19-2006 01:26 PM
subtle side effect of generator/generator expression bonono@gmail.com Python 9 10-16-2005 06:42 PM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
generator function within a generator function doesn't execute? TheDustbustr Python 1 07-25-2003 10:45 AM



Advertisments