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