Welcome, guest | Sign In | My Account | Store | Cart

let's you define a generator with an internal cache that can be accessed like a list

Python, 59 lines
 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]