a break for comprehensions
Tom Good
Tom_Good1 at excite.com
Wed Aug 1 15:24:01 EDT 2001
cjc26 at nospam.cornell.edu (Cliff Crawford) wrote in message news:<U9H97.163512$EF2.22005506 at typhoon.nyroc.rr.com>...
[snip]
> Another possibility would be to have list comprehensions always return a
> generator, and then if you need a list instead, use the built-in
> function list(), for example:
>
> list([x*2 for x in g()])
>
> But this will cause code breakage..maybe the solution to *that* would be
> to add __getitem__(), __len__(), __contains__(), etc. to generator
> objects, so that they can be manipulated as if they were lists. (This
> would solve the original poster's problem too -- you could do g()[:50]
> to get the first 50 items of a generator.)
You've inspired me to start writing a list-like wrapper for
generators. Here is what I have so far. It combines some list syntax
with lazy evaluation, and supports (some) slice operations on
unbounded generators.
from __future__ import generators
class GenList:
"wraps a generator so it will support some list operations"
def __init__(self, gen):
self.gen = gen
self.cachedResults = []
def genNext(self):
self.cachedResults.append(self.gen.next())
def __getitem__(self, i):
if i < 0:
raise IndexError
# negative indices would not work with
# unbounded generators
try:
while len(self.cachedResults) <= i:
self.genNext()
except StopIteration:
pass
return self.cachedResults[i]
def __getslice__(self, i, j):
if i < 0 or j < 0:
raise IndexError
# negative indices would not work with
# unbounded generators
try:
while len(self.cachedResults) <= j:
self.genNext()
except StopIteration:
pass
return self.cachedResults[i:j]
def main():
def gen():
x = 0
while 1:
x += 1
yield x
glist = GenList(gen())
print glist[4]
print glist[:10]
More information about the Python-list
mailing list