How do I extend, mimic, or emulate the range function?

python

Solution

To add to Martin Konecny's answer. You probably want to use an internal range for everything and convert between chr and ord.

class crange:
    def __init__(self, *args, **kwargs):
        args = [ord(arg) for arg in args]
        kwargs = {key: ord(val) for key, val in kwargs.items()}
        self.range = range(*args, **kwargs)

    def __iter__(self):
        for n in self.range:
            yield chr(n)

    def __contains__(self, c):
        return ord(c) in self.range

    def __getitem__(self, i):
        if isinstance(i, slice):
            ret = crange('\x00')
            ret.range = self.range[i]
            return ret
        else:
            return chr(self.range[i])

    def __repr__(self):
        return  "crange({}, {})".format(
            repr(chr(self.range.start)), repr(chr(self.range.stop)))

r = crange('a', 'f')
print(list(r))
print('b' in r)
print('f' in r)
print(r[:2])

In other words: if we can't subclass it we can use object composition.

Problem

I made a little generator function for character ranges: ``` >>> def crange(start, end): ... for i in range(ord(start), ord(end)+1): ... yield chr(i) ... ``` And then I can do this: ``` >>> print(*crange('a','e')) a b c d e ``` Yay! But this doesn't work: ``` >>> crange('a','e')[::2] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'generator' object is not subscriptable ``` And this works, but is O(n), unlike `range`'s O(1): ``` >>> 'y' in crange('a','z') True ``` That means it takes about 0.35 seconds to search for character number 109,999 out of the maximum of 110,000. `109999 in range(110000)` is, of course, fast. At that point, my first thought was to simply subclass range. Unfortunately: ``` >>> class A(range): ... pass ... Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: type 'range' is not an acceptable base type ``` So I guess I would have to mimic it in some way that allows me to pass characters as arguments, works like `range` internally, and produces characters. Unfortunately, I'm not sure how to proceed. I tried a `dir()`: ``` >>> print(*dir(range), sep='\n') __class__ __contains__ __delattr__ __dir__ __doc__ __eq__ __format__ __ge__ __getattribute__ __getitem__ __gt__ __hash__ __init__ __iter__ __le__ __len__ __lt__ __ne__ __new__ __reduce__ __reduce_ex__ __repr__ __reversed__ __setattr__ __sizeof__ __str__ __subclasshook__ count index start step stop ``` which lets me see what functions are in there, but I'm not sure what they're doing, or how `range` uses them. I looked for the source for `range`, but it's in C, and I don't know where to find its Python wrapper (it does have one, right?). Where do I go from here, and should I even go there?

Original source

Related problems