How can I implement a circular range object in Python?
e.g.
Let S is a circular space modulo 2^3 (range [0, 2^3)). I want to generate a range object like this:
crange(3, 7, 2 ** 3) # => a range object [3, 4, 5, 6]
crange(7, 3, 2 ** 3) # => a range object [7, 0, 1, 2]
I tried this:
def crange(start, stop, modulo):
if start > stop:
return range(start, modulo) or range(stop)
else:
return range(start, stop)
But I can't input bigint to crange
e.g. crange(8, 2, 2 ** 160)
.
OverflowError: Python int too large to convert to C ssize_t
I implemented crange
which I want (in reference to @Ni and @J.F.Sebastian).
import math
class crange:
def __init__(self, start, stop, step=None, modulo=None):
if step == 0:
raise ValueError('crange() arg 3 must not be zero')
if step is None and modulo is None:
self.start = 0
self.stop = start
self.step = 1
self.modulo = stop
else:
self.start = start
self.stop = stop
if modulo is None:
self.step = 1
self.modulo = step
else:
self.step = step
self.modulo = modulo
def __iter__(self):
n = self.start
if n > self.stop:
while n < self.modulo:
yield n
n += 1
n = 0
while n < self.stop:
yield n
n += 1
def __contains__(self, n):
if self.start >= self.stop:
return self.start <= n < self.modulo or 0 <= n < self.stop
else:
return self.start <= n < self.stop
I got the following output:
>>> print(list(crange(start=7, stop=3, modulo=2 ** 4)))
[7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2]
>>> print(3 in crange(start=7, stop=3, modulo=2 ** 4))
False
>>> print(7 in crange(start=7, stop=3, modulo=2 ** 4))
True
>>> print(list(crange(start=3, stop=7, modulo=2 ** 4)))
[3, 4, 5, 6]
>>> print(3 in crange(start=3, stop=7, modulo=2 ** 4))
True
>>> print(7 in crange(start=3, stop=7, modulo=2 ** 4))
False