What makes an iterator an iterator?

7stud bbxx789_05ss at yahoo.com
Wed Apr 18 18:41:07 EDT 2007


On Apr 18, 8:50 am, a... at mac.com (Alex Martelli) wrote:
> The special methods need to be on the type -- having attributes of those
> names on the instance doesn't help (applies to all special methods in
> the normal, aka newstyle, object model; legacy, aka classic, classes,
> work by slightly different and not entirely self-consistent semantics).
>
> Alex

Can you explain some of the details of why this code fails:

---
class Parrot(object):
    def __iter__(self):
        return self
    def __init__(self):
        self.next = self.next().next
    def next(self):
        for word in "Norwegian Blue's have beautiful
plumage!".split():
            yield word

P = Parrot()
for word in P:
    print word
------

It causes an infinite loop that just prints out the iterator object
returned when you call the generator function.

If I try this:

-----
class Parrot(object):
    def __iter__(self):
        return self
    def __init__(self):
        print self.next()
        print self.next().next
        #self.next = self.next().next
    def next(self):
        for word in "Norwegian Blue's have beautiful
plumage!".split():
            yield word

P = Parrot()

'''
for word in P:
    print word
'''
----------

the output is:

<generator object at 0x5b080>
<method-wrapper object at 0x55d30>

Based on that output, self.next() is the iterator object that wraps
the generator function, and it has a next() method.  If 'i' is the
iterator object, then the statement:

self.next = self.next().next

is equivalent to:

self.next = i.next

and therefor calling P.next() is equivalent to i.next(), which appears
to be exactly what you want.   As I understand it, this is how the for
loop works:

1) The for loop causes the built in, global iter() function to be
called with P as an argument: iter(P).  That calls P's __iter__()
method, which just returns P.

2) The for loop repeatedly calls next() on whatever object is returned
by 1), so that results in calls to P.next().

3) P.next() is equivalent to i.next()

I don't understand at which step does the code fail.








More information about the Python-list mailing list