On 5/2/2015 5:31 PM, Ian Kelly wrote:
Would it have been better if range() had been implemented as xrange() from the beginning? Sure, that would have been great. Except for one small detail: the iterator protocol didn't exist back then.
For loops originally used the getitem iterator protocol. xrange objects have a __getitem__ method, but not __iter__ or __next__. As Mark pointed out, they were introduced in 1993.
Getitem iterators still work. If iter(ob) is passed object ob without .__iter__, iter looks for ob.__getitem__ and if present, returns iterator(ob), where iterator is an internal protocol adapter class. Its __next__ method calls ob.__getitem__ and converts IndexError to StopIteration.
In 3.4.3: class xrange: def __init__(self, start, stop, step): if step < 1: raise ValueError('incomplete xrange require positive step') self.val = start self.stop = stop self.step = step def __getitem__(self, dummy): val = self.val self.val = val + self.step if val < self.stop: return val else: raise IndexError('') it = iter(xrange(1, 10, 3)) print(type(it)) for i in it: print(i) # <class 'iterator'> 1 4 7 -- Terry Jan Reedy -- https://mail.python.org/mailman/listinfo/python-list