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() _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor