spir wrote: > On 01/24/2014 10:22 AM, Peter Otten wrote: >> >> There's an odd outlier that I probably shouldn't tell you about [...] > > I guess there is a whole class of outliers; not really sure how to > classify them.
I think you are focusing on the details too much. In > class Angles: > def __getitem__ (self, i): > return self.angles[i] * 360 / TAU > def __iter__ (self): > return iter(self.angles) iter(self.angles) is just an implementation detail. The important point is that __iter__() returns a new iterator on each invocation, thus making Angles an "iterable" according to the naming scheme I was trying to establish. The __getitem__() method can be ignored as it is used for element lookup only, not for iteration. > Side question: what is the point of __iter__ on iterators? Take a 'for' > loop like: for x in xs: f(x) > In the case where xs is not an iterator (no __next__), python calls > iter(xs), which IIUC may call xs.__iter__() unless it is a builtin. But if > xs is an iterator (__next__ is there), then Python uses it directly, thus > what is the point of __iter__ there? In any case, python must check > whether xs is an iterator (__next__). So there is no sense in calling > __iter__ on an iterator. Logically, this would lead to an infinite > recursion (calling __iter__ again and again). But python does it anyway > (and stops after the first call, indeed): There is no infinite recursion. The for loop is currently implemented as # expect an iterable # handle iterators through an idempotent iter() tmp = iter(xs) while True: try: x = next(tmp) except StopIteration: break # use x If I understand you correctly you suggest the following: # expect an iterator # fall back to getting an iterator through iter() try: tmp = xs.__next__ except AttributeError: tmp = iter(xs).__next__ while True: try: x = tmp() except StopIteration: break How is that simpler? > The only theoretical case I can find is iterators which do implement the > protocol (__next__) but are not to be used (!), instead delegate to > another iterator. Again: the important differentiation is between iterator and iterable, not how the iterator is implemented. > Then, why do they bear __next__ at all? why are they > iterators at all? Python allows you to do things that make no sense from the point of view of a human being. You can also implement an integer type with a negative abs(): >>> class Int(int): ... def __abs__(self): return self ... >>> abs(Int(-1)) -1 My advice: don't do it unless you have a good reason. _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor