itertools.flatten()? and copying generators/iterators.

Francis Avila francisgavila at yahoo.com
Tue Oct 28 07:56:48 EST 2003


"Raymond Hettinger" <vze4rx4y at verizon.net> wrote in message
news:niqnb.17753$294.1079 at nwrdny03.gnilink.net...
> [Francis Avila]

> > Also, why is the iterator type not included in the types module or
described
> > in the language reference (Python 2.2)?
>
> There is no iterator type.  Iterators can be any object that supports the
> iterator
> protocol: __iter__() and next().  Generators, container iterators, and
each of
> the itertools define their own type.

Actually (Python 2.2):

>>> IteratorType = type(iter(()))
>>> IteratorType
<type 'iterator'>
>>> from types import GeneratorType
>>> GeneratorType
<type 'generator'>
>>> GeneratorType == IteratorType
0
>>> isinstance(IteratorType, GeneratorType)
0
>>> isinstance(GeneratorType, IteratorType)
0
>>> dir(GeneratorType)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__iter__', '__new__', '__reduce__', '__repr__', '__setattr__',
'__str__', 'gi_frame', 'gi_running', 'next']
>>> dir(IteratorType)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__iter__', '__new__', '__reduce__', '__repr__', '__setattr__',
'__str__', 'next']
>>> def g():
 yield None


>>> G = g()
>>> type(G)
<type 'generator'>
>>> G
<generator object at 0x0156F1C0>
>>> iter(G)
<generator object at 0x0156F1C0>
>>> I = iter(())
>>> type(I)
<type 'iterator'>
>>> I
<iterator object at 0x014BAC80>
>>> iter(I)
<iterator object at 0x014BAC80>
>>>

The generator seems to be an actual execution frame, but an iterator only a
type that supports the iterator protocol. I think from this that iterator
needs to store all its elements prior to yielding them, whereas a generator
does not. For this reason, an iterator will always terminate eventually.
For these two reasons, I think it's useful to distinguish iterators and
generators.

I think I've clarified it a bit more to myself. For iterators, it iterates
infinitely if it yields itself, otherwise it doesn't.  For generators, it is
unknowable.

Are classes supporting the iterator protocol always generators? Would they
*ever* be an iterator? (According to type(), I mean)  Is there any other way
to get a strict iterator other than applying iter() to a sequence?  (I
noticed you can't force Python to subclass the iterator type.)

The language reference (or maybe it's the module reference?) states that
generators yield iterator objects. That's not exactly true: they yield
generator objects which support the iterator protocol, but not iterator
objects.  And again, iterator types are not mentioned as a separate type in
the language reference, which strikes me as odd.

Perhaps a guru can clarify the relationship between generators and
iterators?
--
Francis Avila





More information about the Python-list mailing list