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