beginning index for generators
Peter Otten
__peter__ at web.de
Sat Oct 16 11:03:46 EDT 2004
kosh wrote:
> I was wondering if there is or there could be some way to pass a generator
> an optional starting index so that if it supported that slicing could be
> made more efficient. Right now if you do use a generator and do a
> [100:110] or any other kind of slice it reads all the values up to 100
> also.
Here is an 'iterate' class that decides whether to use iteration over or
indexed access of items based on the existence of a __getitem__() method.
It's mostly a proof of concept and not tested beyond what you see below.
Peter
import itertools, sys
def irange(start, stop, step):
if start is None:
start = 0
if step is None:
step = 1
index = start
if stop is None:
while True:
yield index
index += step
else:
if step < 0:
while index > stop:
yield index
index += step
else:
while index < stop:
yield index
index += step
def islice(iterable, start, step, stop):
if start is None: start = 0
if step is None: step = 1
return itertools.islice(iterable, start, stop, step)
class iterate(object):
def __init__(self, iterable):
self.iterable = iterable
def __getitem__(self, s):
if not isinstance(s, slice):
raise ValueError("supports only slices")
start, stop, step = s.start, s.stop, s.step
if hasattr(self.iterable, "__getitem__"):
indexable = self.iterable
def iterate():
for index in irange(start, stop, step):
yield indexable[index]
return iterate()
return islice(self.iterable, start, step, stop)
class Sequential(object):
def __init__(self):
self.index = 0
def __iter__(self):
return self
def next(self):
print "sequential[%s]" % self.index
try:
return self.index
finally:
self.index += 1
class Random(Sequential):
def __getitem__(self, index):
print "random[%s]" % index
return index
def printThem(iterable):
for i in iterable:
print i
print "---"
printThem(iterate(Random())[3:10:2])
printThem(iterate(Random())[3:10])
printThem(iterate(Sequential())[3:10:2])
printThem(iterate(Sequential())[3:10])
# I'd rather not:
# printThem(iterate(Sequential())[sys.maxint-10::3])
printThem(itertools.islice(iterate(Random())[sys.maxint-5::3], 10))
More information about the Python-list
mailing list