[Tutor] PolyRange -- iterator
spir
denis.spir at free.fr
Wed Nov 4 17:38:48 CET 2009
Hello,
as I was crawling in endless complications with unadequate ranges, I decided to create a "PolyRange" type able to hold arbitrary many "sub-range"; which means finally a big range with wholes in it. This whole stuff again to cope with unicode -- a poly-range would be able to hold a range for a char class (eg 'letter') which spans over several ordinal ranges. (Viva unicode consortium!)
So, it works as needed. It is even able to "stretch" over addictional sub-ranges or to "unite" with a poly-range brother (sister, too). See code below.
Now, I need it to be properly iterable if needed -- the main use beeing indeed the 'in' operator -- but who knows. So, I tried to implement __iter__ and next (by the way, why isin't it called __next__ instead, looks strange for a python builtin?). Seems to work, but the result looks veeery heavy to my eyes. As I had never written an iterator before, would be nice and criticize the code?
Thank you,
Denis
-------
la vita e estrany
==========================================================
class PolyRange(object):
def __init__(self, *bounds):
''' Build list of ranges from bounds.
* bounds must sequence of (n1,n2) pairs. '''
self.bounds = list(bounds)
self.ranges = [xrange(n1,n2) for (n1,n2) in bounds]
# iteration
def __contains__(self, item):
''' x in self '''
for range in self.ranges:
if item in range:
return True
def __or__(self, other):
''' PolyRange union '''
bounds = self.bounds + other.bounds
return PolyRange(*bounds)
def __add__(self, range):
''' PolyRange with new range added '''
n1 = range[0] ; n2 = n1+len(range)
bounds = self.bounds + [(n1,n2)]
return PolyRange(*bounds)
def __iter__(self):
self.isEmpty = False
(self.range_index, self.item_index) = (0,0)
self.iter = self.ranges[0].__iter__()
return self
def next(self):
# case already emptied
if self.isEmpty:
raise StopIteration
# throw next item
try:
item = self.iter.next()
except StopIteration:
self.range_index += 1
self.item_index = 0
else:
self.item_index += 1
return item
# next range
if len(self.ranges) > self.range_index:
self.iter = self.ranges[self.range_index].__iter__()
else:
self.empty = True
raise StopIteration
# throw item
try:
item = self.iter.next()
except StopIteration:
self.empty = True
raise StopIteration
else:
self.item_index += 1
return item
def __str__(self):
return "(%s)" %'U'.join("[%s,%s)" %(n1,n2) for (n1,n2) in self.bounds)
def __repr__(self):
return "PolyRange(%s)" %', '.join(str(b) for b in self.bounds)
return False
def testPolyRange():
print "=== base case -- test in/contains"
pr = PolyRange((1,3),(5,7),(9,11))
print "%s\t%s" %(pr,repr(pr))
print 2 in pr, 4 in pr
print "=== union"
pr = PolyRange((1,3),(5,7)) | PolyRange((9,11))
print pr
print "=== addition, iteration"
r = xrange(3,9)
pr0 = PolyRange((1,3),(5,7))
pr1 = pr0 + r
print pr1
for i in pr1: print i,
testPolyRange()
More information about the Tutor
mailing list