Hi, Thanks for the responses.
> 7stud <[EMAIL PROTECTED]> wrote: > > 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 > ------ On Apr 18, 8:45 pm, [EMAIL PROTECTED] (Alex Martelli) wrote: > > ...a loop like "for x in y:" binds an unnamed temporary > variable (say _t) to iter(y) and then repeatedly calls _t.next() [or to > be pedantic type(_t).next(t)] until that raises StopIteration. Aiiii. Isn't this the crux: > repeatedly calls....[type(_t).next(t)] As far as I can tell, if the call was actually _t.next(), the code I asked about would work. However, the name look up for 'next' when you call: P.next() is entirely different from the name look up for 'next' when you call: type(P).next(). In the first lookup, the instance attribute "next" hides the class attribute "next". In the second lookup, the "next" attribute of the class is returned, i.e. the next() method. Yet, a generator-function- call returns an iterator object that wraps the generator function, so when the for loop makes repeated calls to type(P).next(), an iterator object is repeatedly returned--what you want is i.next() to be returned. I suspected next() might be called through the class, but after carefully parsing the section on iterators (Python in a Nutshell, p. 65) where it says iter() returns an object i, and then the for loop repeatedly calls i.next(), I dismissed that idea. I have to admit I'm still a little confused by why you only parenthetically noted that information and called it pedantic. On Apr 18, 8:38 pm, "Terry Reedy" <[EMAIL PROTECTED]> wrote: > > One very good way to get an iterator from an iterable is for .__iter__ to > be a generator function. Ahhh. That eliminates having to deal with next().next constructs. Nice. > snip all examples of bad code that violate the iterator rule > by improperly writing .next as a generator function What iterator rule states that .next can't be a generator function? My book says an iterator is any object with a .next method that is callable without arguments (Python in a Nutshell(p.65) says the same thing). Also, my boos says an iterable is any object with an __iter__ method. As a result, next() and __iter__() don't have to be in the same object: lass MyIterator(object): def __init__(self, obj): self.toIterateOver = obj def next(self): for x in range(self.toIterateOver.age): print x raise StopIteration class Dog(object): def __init__(self, age): self.age = age def __iter__(self): return MyIterator(self) d = Dog(5) for year in d: print year I've read recommendations that an iterator should additionally contain an __iter__() method, but I'm not sure why that is. In particular PEP 234 says: ---------- Classes can define how they are iterated over by defining an __iter__() method; this should take no additional arguments and return a valid iterator object. A class that wants to be an iterator should implement two methods: a next() method that behaves as described above, and an __iter__() method that returns self. The two methods correspond to two distinct protocols: 1. An object can be iterated over with "for" if it implements __iter__() or __getitem__(). 2. An object can function as an iterator if it implements next(). Container-like objects usually support protocol 1. Iterators are currently required to support both protocols. The semantics of iteration come only from protocol 2; protocol 1 is present to make iterators behave like sequences; in particular so that code receiving an iterator can use a for-loop over the iterator. Classes can define how they are iterated over by defining an __iter__() method; this should take no additional arguments and return a valid iterator object. A class that wants to be an iterator should implement two methods: a next() method that behaves as described above, and an __iter__() method that returns self. The two methods correspond to two distinct protocols: 1. An object can be iterated over with "for" if it implements __iter__() or __getitem__(). 2. An object can function as an iterator if it implements next(). Container-like objects usually support protocol 1. Iterators are currently required to support both protocols. The semantics of iteration come only from protocol 2; protocol 1 is present to make iterators behave like sequences; in particular so that code receiving an iterator can use a for-loop over the iterator. -------- >The semantics of > iteration come only from protocol 2 My example demonstrates that. >protocol 1 is present to make > iterators behave like sequences; in particular so that code > receiving an iterator can use a for-loop over the iterator. I don't understand that part--it looks like my example is using a for loop over the iterator. -- http://mail.python.org/mailman/listinfo/python-list