Interesting point! You can more or less do this with a class. Here
is a simple example; it yields the first n elements of the Fibonacci
sequence (1, 1, 2, 3, 5, 8, 13, ...):
class Fib:
# constructor -- argument is length of sequence
def __init__(self, n):
self.size = n
self.reset()
def reset(self):
self.last_index = 0
self.a = self.b = 1
# return len(self)
def __len__(self):
return self.size
# return self[i]
def __getitem__(self, i):
if i < self.last_index:
self.reset()
while i > self.last_index:
self.last_index = self.last_index + 1
self.a, self.b = self.b, self.a + self.b
return self.a
This example tries to behave like a real sequence -- only it is faster
when you ask for the items in their natural sequence, hence the
reset() method. For iterators that will *only* be used in a for loop,
__getitem__ could raise an expression when an item is asked for out of
sequence.
The catch is that you need to know how many values a particular
iterator instance will yield, so you can't use it to simulate an
infinite or indefinite sequence.
If iterators become popular in Python, it might be possible to
redefine the 'for' semantics and extend the interface to sequences to
allow for loops over (pseudo-)sequences of indefinite length. But I
don't know how much use there is for this, since it is generally just
as easy to use a while loop for a loop over an indefinite sequence...
--Guido van Rossum, CWI, Amsterdam <Guido.van.Rossum@cwi.nl>