Christopher Spears schreef: > How does this script work? > > #!/usr/bin/python > > class IteratorExample: > def __init__(self, s): > self.s = s > self.next = self._next().next > self.exhausted = 0 > def _next(self): > if not self.exhausted: > flag = 0 > for x in self.s: > if flag: > flag = 0 > yield x > else: > flag = 1 > self.exhausted = 1 > def __iter__(self): > return self._next() > > def main(): > a = IteratorExample('edcba') > for x in a: > print x
Maybe I should try to explain what's happening instead of only offering an alternative. It's somewhat complicated by the fact that this is a very convoluted example IMO. To be able to use an object in a for loop like that, it needs an __iter__() method. That method is called behind the scenes when the for loop is started, and it should return an iterator object. An iterator object is an object with a next() method that returns the next element each time it's called, and raises StopIteration if there are no more elements. Useless but simple example: class Count: def __init__(self): self.max = 10 self.index = 0 def __iter__(self): return self def next(self): self.index += 1 if self.index > self.max: raise StopIteration return self.index Objects instantiated from this class can be iterated over because of the __iter__() method. In this case, that method returns the object itself; therefore the object itself serves as the iterator object. It does this with its next() method, which simply returns the numbers 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 and then raises StopIteration. A special kind of iterator object can be made with a generator function. That looks like a normal function, but uses yield instead of return. Each time its next element is requested, it runs until it encounters a yield statement. At that point, it passes the value specified in the yield statement to its caller and then freezes. When the next element is requested, it resumes operation directly after the yield statement where it was frozen until it encounters the next yield statement. And so on, until the function ends or executes the return statement or raises StopIteration. Again, a simple example: def backwards(s): for x in s[::-1]: yield x for x in backwards('edcba'): print x a b c d e Now, in your example the two are mixed. To make matters somewhat less complicated, I commented some lines that are totally useless; you should ignore them: class IteratorExample: def __init__(self, s): self.s = s #self.next = self._next().next #self.exhausted = 0 def _next(self): #if not self.exhausted: flag = 0 for x in self.s: if flag: flag = 0 yield x else: flag = 1 #self.exhausted = 1 def __iter__(self): return self._next() The _next() method is a generator function as I described above, which creates an iterator object when called. The __iter__() method just calls that generator function and returns the result to its caller. HTH -- If I have been able to see further, it was only because I stood on the shoulders of giants. -- Isaac Newton Roel Schroeven _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor