let's you define a generator with an internal cache that can be accessed like a list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59  | import tempfile, sqlobject
class SubscriptableGenerator(object):
    
    class Data(sqlobject.SQLObject):
        data = sqlobject.PickleCol()
        
    def __init__(self, sqlite=None):
        if not sqlite:
            sqlite = tempfile.mkstemp('.db', 'subGenCache-')[1]            
            
        self.sqlite = sqlite
        uri = "sqlite://%s" % sqlite                
        c = sqlobject.connectionForURI(uri)
        sqlobject.sqlhub.processConnection = c            
        SubscriptableGenerator.Data.createTable(ifNotExists=True)
        
        self._genCounter = 1
        
    def __iter__(self):
        return self
          
    def next(self):            
        try:
            ret = SubscriptableGenerator.Data.get(self._genCounter).data
        except:
            try:
                ret = self.gen()
                SubscriptableGenerator.Data(data=ret)
            except StopIteration:
                raise StopIteration
        self._genCounter += 1
        return ret
    
    def _getFromCache(self, i):
        try:
            ret = SubscriptableGenerator.Data.get(i+1).data
        except:
            ret = self.gen()
            SubscriptableGenerator.Data(id=i+1, data=ret)
            
        #self._genCounter += 1
        return ret
    
    def __getitem__(self, k):
        if isinstance(k, slice):
            [self._getFromCache(i) for i in xrange(0, k.start)]
            
            return [self._getFromCache(i) for i in xrange(k.start, k.stop, 1 if k.start < k.stop else -1)]
        else:
            return self._getFromCache(k)
    
    # irreversible without a flush due to the fact that
    # the generator isn't called unless the _cache[k] is undefined
    def __setitem__(self, k, v):
        val = SubscriptableGenerator.Data.get(k+1)
        val.data = v
        
    def gen(self):
        raise NotImplementedError
 | 
class Gen(SubscriptableGenerator): def __init__(self, max): super(Gen, self).__init__() self.range = xrange(0, max).__iter__()
def gen(self):
    return self.range.next()
g = Gen(10)
print g[1:7] for i in g: print i g[2] = 'omg' print g[0:4] print g[4:0]
outputs
[1, 2, 3, 4, 5, 6]
0
1
2
3
4
5
6
7
8
9
[0, 1, 'omg', 3]
[4, 3, 'omg', 1]
    Tags: extending
  
  
      
Download
Copy to clipboard