Iterator - what I am missing

H

Helmut Jarausch

Hi,

I cannot find out what I miss with my iterator example.

I have a linked list class Queue which has a 'Head' attribute
and the following

def __iter__(self):
if self.Head == None: raise StopIteration
return self.Head

The elements of the list are of class Node

which has a 'NNd' (next Node) attribute and
a next method

def next(self):
N= self.NNd
if N == None: raise StopIteration
return N

Now when I try to iterate over all elements of the
Queue like in (MyQ is an instance of class Queue)

for N in MyQ:
print "loop->",N
print N.key,N.data

I get an infinite loop and 'N' always refers to the first
element of the MyQ as initialized by MyQ.__iter__

I've checked 'MyQ' and it contains 2 elements and 'NNd'
attribute of the last one is 'None'

So what's going on here?

Many thanks for a hint,

Helmut Jarausch

Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany
 
M

Michael Peuser

Hi Helmut,

the information you give is *very* imcomplete ;-) Probably the *next* method
is in the wrong class (Node instead of Queue). But one can only help with
the full code of both classes...

Have you considered using the new generators? They are not as new (from
__future__ import generators) if you will not use Python 2.3. They make
iterators much more transparent!

Kindly
Michael P
 
T

Terry Reedy

Helmut Jarausch said:
Hi,

I cannot find out what I miss with my iterator example.

I have a linked list class Queue which has a 'Head' attribute
and the following

def __iter__(self):
if self.Head == None: raise StopIteration
return self.Head

The .__iter__ method of an iterable must return an iterater. If an
object is its own iterator (ie, has a proper .next() method, then
'return self' is the proper return. If an object does not, then
..__iter__ can be written as a generator (which, when called, returns a
generator iterator).

Based on your node description below, the following might work.

def __iter__(self):
current = self.Head
while 1:
if current == None: raise StopIteration
yield current
current = current.NNd()

The elements of the list are of class Node

which has a 'NNd' (next Node) attribute and
a next method

def next(self):
N= self.NNd
if N == None: raise StopIteration
return N

This by itself cannot iterate since self is an item in the sequence
and neither the sequence nor a separate iterator object such as
returned from the call to my __iter__ suggestion above.

Terry J. Reedy
 
P

Peter Otten

Terry said:
def __iter__(self):
current = self.Head
while 1:
if current == None: raise StopIteration
yield current
current = current.NNd()

This can be simplified:

<untested>

def __iter__(self):
current = self.head # uppercase attributes are ugly
while current is not None:
yield current
current = current.nextNode() # no crptc abrvtns pls, Helmut :)

</untested>

The StopIteration exception is raised implicitely at the end of the method

Peter
 

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

Forum statistics

Threads
474,085
Messages
2,570,597
Members
47,220
Latest member
AugustinaJ

Latest Threads

Top