Pure python range implementationPython implementation of SHA1ECDH implementation in pythonLSB steganography with pure PythonPython implementation for contains pattern in textPython implementation for Setiterative binary_search Python implementationis_subset Python implementationPython Float point range() operator implementationContinuous Range classPython implementation of atoi

Why is it called a stateful and a stateless firewall?

Beauville-Laszlo for schemes

What is the origin of the "being immortal sucks" trope?

Latex matrix formatting

How to generate short fixed length cryptographic hashes?

Tips for remembering the order of parameters for ln?

What is the difference between an engine skirt and an engine nozzle?

How would you translate Evangelii Nuntiandi?

Why would a fighter use the afterburner and air brakes at the same time?

In Bb5 systems against the Sicilian, why does White exchange their b5 bishop without playing a6?

Very lazy puppy

Pure python range implementation

Madrid to London w/ Expired 90/180 days stay as US citizen

Have you ever been issued a passport or national identity card for travel by any other country?

What's the benefit of prohibiting the use of techniques/language constructs that have not been taught?

What is this WWII four-engine plane on skis?

Why are two-stroke engines nearly unheard of in aviation?

What does “We have long ago paid the goblins of Moria,” from The Hobbit mean?

Wouldn't Kreacher have been able to escape even without following an order?

How to give my students a straightedge instead of a ruler

Python web-scraper to download table of transistor counts from Wikipedia

Statistical tests for benchmark comparison

Does household ovens ventilate heat to the outdoors?

Anagrams Question



Pure python range implementation


Python implementation of SHA1ECDH implementation in pythonLSB steganography with pure PythonPython implementation for contains pattern in textPython implementation for Setiterative binary_search Python implementationis_subset Python implementationPython Float point range() operator implementationContinuous Range classPython implementation of atoi






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








8












$begingroup$


I implemented class Range as an equivalent to Python built-in range for practicing purposes. No features were added. Hope it mimics all aspects of range behavior, but maybe you can point out something I forgot. Also I tried to make the code efficient, that's why Range doesn't inherit from collections.abc.Sequence and doesn't use any of it's not abstract methods. All feedback on how to improve the code is welcome!



pyrange.py



"""
Pure Python implementation of built-in range
"""


import math
import collections.abc
import numbers


def interpret_as_integer(obj):
if hasattr(obj, '__index__'):
return obj.__index__()
raise TypeError(
''' object cannot be interpreted as an integer'.format(
type(obj).__name__
)
)


def adjust_indices(length, start, stop, step):
if step is None:
step = 1
else:
step = interpret_as_integer(step)

if start is None:
start = length - 1 if step < 0 else 0
else:
start = interpret_as_integer(start)
if start < 0:
start += length
if start < 0:
start = -1 if step < 0 else 0
elif start >= length:
start = length - 1 if step < 0 else length

if stop is None:
stop = -1 if step < 0 else length
else:
stop = interpret_as_integer(stop)
if stop < 0:
stop += length
if stop < 0:
stop = -1 if step < 0 else 0
elif stop >= length:
stop = length - 1 if step < 0 else length

return start, stop, step


class Range:
"""
Range(stop) -> Range object
Range(start, stop[, step]) -> Range object

Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. Range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! Range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
"""

__slots__ = ('start', 'stop', 'step', '_len')

def __init__(self, start, stop=None, step=1):
if stop is None:
start, stop = 0, start
self.start, self.stop, self.step = (
interpret_as_integer(obj) for obj in (start, stop, step)
)
if step == 0:
raise ValueError('Range() arg 3 must not be zero')
step_sign = int(math.copysign(1, self.step))
self._len = max(
1 + (self.stop - self.start - step_sign) // self.step, 0
)

def __contains__(self, value):
if isinstance(value, numbers.Integral):
return self._index(value) != -1
return any(n == value for n in self)

def __eq__(self, other):
if not isinstance(other, Range):
return False
if self._len != len(other):
return False
if self._len == 0:
return True
if self.start != other.start:
return False
if self[-1] == other[-1]:
return True
return False

def __getitem__(self, index):
if isinstance(index, slice):
start, stop, step = adjust_indices(
self._len, index.start, index.stop, index.step
)
return Range(
self.start + self.step * start,
self.start + self.step * stop,
self.step * step
)
index = interpret_as_integer(index)
if index < 0:
index += self._len
if not 0 <= index < self._len:
raise IndexError('Range object index out of Range')
return self.start + self.step * index

def __hash__(self):
if self._len == 0:
return id(Range)
return hash((self._len, self.start, self[-1]))

def __iter__(self):
value = self.start
if self.step > 0:
while value < self.stop:
yield value
value += self.step
else:
while value > self.stop:
yield value
value += self.step

def __len__(self):
return self._len

def __repr__(self):
if self.step == 1:
return 'Range(, )'.format(self.start, self.stop)
return 'Range(, , )'.format(self.start, self.stop, self.step)

def __reversed__(self):
return iter(self[::-1])

def _index(self, value):
index_mul_step = value - self.start
if index_mul_step % self.step:
return -1
index = index_mul_step // self.step
if 0 <= index < self._len:
return index
return -1

def count(self, value):
"""
Rangeobject.count(value) -> integer
Return number of occurrences of value.
"""
return sum(1 for n in self if n == value)

def index(self, value, start=0, stop=None):
"""
Rangeobject.index(value, [start, [stop]]) -> integer
Return index of value.
Raise ValueError if the value is not present.
"""
if start < 0:
start = max(self._len + start, 0)
if stop is None:
stop = self._len
if stop < 0:
stop += self._len

if isinstance(value, numbers.Integral):
index = self._index(value)
if start <= index < stop:
return index
raise ValueError(' is not in Range'.format(value))

i = start
n = self.start + self.step * i
while i < stop:
if n == value:
return i
i += 1
n += self.step
raise ValueError(' is not in Range'.format(value))


collections.abc.Sequence.register(Range)


test_pyrange.py



# pylint: disable = too-few-public-methods

import itertools

from pyrange import Range


class Equal:
def __eq__(self, other):
return True


class Indexable:
def __init__(self, n):
self.n = n

def __index__(self):
return self.n


def test_basic():
small_builtin_range = range(10)
small_my_range = Range(10)
equal = Equal()
assert small_builtin_range.count(equal) == small_my_range.count(equal) == 10
assert small_my_range.index(equal) == small_my_range.index(equal) == 0

big_my_range = Range(0, 10 ** 20, 10 ** 5)
assert 10 ** 15 in big_my_range
assert big_my_range[Indexable(10 ** 3)] == 10 ** 8
assert big_my_range[
Indexable(10 ** 3):Indexable(10 ** 6):Indexable(10 ** 2)
] == Range(10 ** 8, 10 ** 11, 10 ** 7)


def test_slicing():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for slice_start, slice_stop, slice_step in itertools.product(
list(range(-3, 3)) + [None], repeat=3
):
if slice_step == 0:
continue
slc = slice(slice_start, slice_stop, slice_step)
builtin_range_slice = builtin_range[slc]
my_range_slice = my_range[slc]
for name in ('start', 'stop', 'step'):
assert (
getattr(builtin_range_slice, name) ==
getattr(my_range_slice, name)
), (start, stop, step, slice_start, slice_stop, slice_step)


def test_eq_and_hash():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for start_2, stop_2, step_2 in itertools.product(
range(-3, 3), repeat=3
):
if step_2 == 0:
continue
builtin_range_2 = range(start_2, stop_2, step_2)
my_range_2 = Range(start_2, stop_2, step_2)
if builtin_range == builtin_range_2:
assert my_range == my_range_2, (
start, stop, step, start_2, stop_2, step_2
)
assert hash(my_range) == hash(my_range_2), (
start, stop, step, start_2, stop_2, step_2
)









share|improve this question









New contributor



sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$













  • $begingroup$
    Your constructor is __init__(start, stop=None, step=1). Shouldn't start be optional and stop positional? range(3) means [0, 1, 2], not [3, 4, 5, ...].
    $endgroup$
    – Jack M
    9 hours ago










  • $begingroup$
    @JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
    $endgroup$
    – sanyash
    9 hours ago

















8












$begingroup$


I implemented class Range as an equivalent to Python built-in range for practicing purposes. No features were added. Hope it mimics all aspects of range behavior, but maybe you can point out something I forgot. Also I tried to make the code efficient, that's why Range doesn't inherit from collections.abc.Sequence and doesn't use any of it's not abstract methods. All feedback on how to improve the code is welcome!



pyrange.py



"""
Pure Python implementation of built-in range
"""


import math
import collections.abc
import numbers


def interpret_as_integer(obj):
if hasattr(obj, '__index__'):
return obj.__index__()
raise TypeError(
''' object cannot be interpreted as an integer'.format(
type(obj).__name__
)
)


def adjust_indices(length, start, stop, step):
if step is None:
step = 1
else:
step = interpret_as_integer(step)

if start is None:
start = length - 1 if step < 0 else 0
else:
start = interpret_as_integer(start)
if start < 0:
start += length
if start < 0:
start = -1 if step < 0 else 0
elif start >= length:
start = length - 1 if step < 0 else length

if stop is None:
stop = -1 if step < 0 else length
else:
stop = interpret_as_integer(stop)
if stop < 0:
stop += length
if stop < 0:
stop = -1 if step < 0 else 0
elif stop >= length:
stop = length - 1 if step < 0 else length

return start, stop, step


class Range:
"""
Range(stop) -> Range object
Range(start, stop[, step]) -> Range object

Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. Range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! Range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
"""

__slots__ = ('start', 'stop', 'step', '_len')

def __init__(self, start, stop=None, step=1):
if stop is None:
start, stop = 0, start
self.start, self.stop, self.step = (
interpret_as_integer(obj) for obj in (start, stop, step)
)
if step == 0:
raise ValueError('Range() arg 3 must not be zero')
step_sign = int(math.copysign(1, self.step))
self._len = max(
1 + (self.stop - self.start - step_sign) // self.step, 0
)

def __contains__(self, value):
if isinstance(value, numbers.Integral):
return self._index(value) != -1
return any(n == value for n in self)

def __eq__(self, other):
if not isinstance(other, Range):
return False
if self._len != len(other):
return False
if self._len == 0:
return True
if self.start != other.start:
return False
if self[-1] == other[-1]:
return True
return False

def __getitem__(self, index):
if isinstance(index, slice):
start, stop, step = adjust_indices(
self._len, index.start, index.stop, index.step
)
return Range(
self.start + self.step * start,
self.start + self.step * stop,
self.step * step
)
index = interpret_as_integer(index)
if index < 0:
index += self._len
if not 0 <= index < self._len:
raise IndexError('Range object index out of Range')
return self.start + self.step * index

def __hash__(self):
if self._len == 0:
return id(Range)
return hash((self._len, self.start, self[-1]))

def __iter__(self):
value = self.start
if self.step > 0:
while value < self.stop:
yield value
value += self.step
else:
while value > self.stop:
yield value
value += self.step

def __len__(self):
return self._len

def __repr__(self):
if self.step == 1:
return 'Range(, )'.format(self.start, self.stop)
return 'Range(, , )'.format(self.start, self.stop, self.step)

def __reversed__(self):
return iter(self[::-1])

def _index(self, value):
index_mul_step = value - self.start
if index_mul_step % self.step:
return -1
index = index_mul_step // self.step
if 0 <= index < self._len:
return index
return -1

def count(self, value):
"""
Rangeobject.count(value) -> integer
Return number of occurrences of value.
"""
return sum(1 for n in self if n == value)

def index(self, value, start=0, stop=None):
"""
Rangeobject.index(value, [start, [stop]]) -> integer
Return index of value.
Raise ValueError if the value is not present.
"""
if start < 0:
start = max(self._len + start, 0)
if stop is None:
stop = self._len
if stop < 0:
stop += self._len

if isinstance(value, numbers.Integral):
index = self._index(value)
if start <= index < stop:
return index
raise ValueError(' is not in Range'.format(value))

i = start
n = self.start + self.step * i
while i < stop:
if n == value:
return i
i += 1
n += self.step
raise ValueError(' is not in Range'.format(value))


collections.abc.Sequence.register(Range)


test_pyrange.py



# pylint: disable = too-few-public-methods

import itertools

from pyrange import Range


class Equal:
def __eq__(self, other):
return True


class Indexable:
def __init__(self, n):
self.n = n

def __index__(self):
return self.n


def test_basic():
small_builtin_range = range(10)
small_my_range = Range(10)
equal = Equal()
assert small_builtin_range.count(equal) == small_my_range.count(equal) == 10
assert small_my_range.index(equal) == small_my_range.index(equal) == 0

big_my_range = Range(0, 10 ** 20, 10 ** 5)
assert 10 ** 15 in big_my_range
assert big_my_range[Indexable(10 ** 3)] == 10 ** 8
assert big_my_range[
Indexable(10 ** 3):Indexable(10 ** 6):Indexable(10 ** 2)
] == Range(10 ** 8, 10 ** 11, 10 ** 7)


def test_slicing():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for slice_start, slice_stop, slice_step in itertools.product(
list(range(-3, 3)) + [None], repeat=3
):
if slice_step == 0:
continue
slc = slice(slice_start, slice_stop, slice_step)
builtin_range_slice = builtin_range[slc]
my_range_slice = my_range[slc]
for name in ('start', 'stop', 'step'):
assert (
getattr(builtin_range_slice, name) ==
getattr(my_range_slice, name)
), (start, stop, step, slice_start, slice_stop, slice_step)


def test_eq_and_hash():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for start_2, stop_2, step_2 in itertools.product(
range(-3, 3), repeat=3
):
if step_2 == 0:
continue
builtin_range_2 = range(start_2, stop_2, step_2)
my_range_2 = Range(start_2, stop_2, step_2)
if builtin_range == builtin_range_2:
assert my_range == my_range_2, (
start, stop, step, start_2, stop_2, step_2
)
assert hash(my_range) == hash(my_range_2), (
start, stop, step, start_2, stop_2, step_2
)









share|improve this question









New contributor



sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$













  • $begingroup$
    Your constructor is __init__(start, stop=None, step=1). Shouldn't start be optional and stop positional? range(3) means [0, 1, 2], not [3, 4, 5, ...].
    $endgroup$
    – Jack M
    9 hours ago










  • $begingroup$
    @JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
    $endgroup$
    – sanyash
    9 hours ago













8












8








8





$begingroup$


I implemented class Range as an equivalent to Python built-in range for practicing purposes. No features were added. Hope it mimics all aspects of range behavior, but maybe you can point out something I forgot. Also I tried to make the code efficient, that's why Range doesn't inherit from collections.abc.Sequence and doesn't use any of it's not abstract methods. All feedback on how to improve the code is welcome!



pyrange.py



"""
Pure Python implementation of built-in range
"""


import math
import collections.abc
import numbers


def interpret_as_integer(obj):
if hasattr(obj, '__index__'):
return obj.__index__()
raise TypeError(
''' object cannot be interpreted as an integer'.format(
type(obj).__name__
)
)


def adjust_indices(length, start, stop, step):
if step is None:
step = 1
else:
step = interpret_as_integer(step)

if start is None:
start = length - 1 if step < 0 else 0
else:
start = interpret_as_integer(start)
if start < 0:
start += length
if start < 0:
start = -1 if step < 0 else 0
elif start >= length:
start = length - 1 if step < 0 else length

if stop is None:
stop = -1 if step < 0 else length
else:
stop = interpret_as_integer(stop)
if stop < 0:
stop += length
if stop < 0:
stop = -1 if step < 0 else 0
elif stop >= length:
stop = length - 1 if step < 0 else length

return start, stop, step


class Range:
"""
Range(stop) -> Range object
Range(start, stop[, step]) -> Range object

Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. Range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! Range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
"""

__slots__ = ('start', 'stop', 'step', '_len')

def __init__(self, start, stop=None, step=1):
if stop is None:
start, stop = 0, start
self.start, self.stop, self.step = (
interpret_as_integer(obj) for obj in (start, stop, step)
)
if step == 0:
raise ValueError('Range() arg 3 must not be zero')
step_sign = int(math.copysign(1, self.step))
self._len = max(
1 + (self.stop - self.start - step_sign) // self.step, 0
)

def __contains__(self, value):
if isinstance(value, numbers.Integral):
return self._index(value) != -1
return any(n == value for n in self)

def __eq__(self, other):
if not isinstance(other, Range):
return False
if self._len != len(other):
return False
if self._len == 0:
return True
if self.start != other.start:
return False
if self[-1] == other[-1]:
return True
return False

def __getitem__(self, index):
if isinstance(index, slice):
start, stop, step = adjust_indices(
self._len, index.start, index.stop, index.step
)
return Range(
self.start + self.step * start,
self.start + self.step * stop,
self.step * step
)
index = interpret_as_integer(index)
if index < 0:
index += self._len
if not 0 <= index < self._len:
raise IndexError('Range object index out of Range')
return self.start + self.step * index

def __hash__(self):
if self._len == 0:
return id(Range)
return hash((self._len, self.start, self[-1]))

def __iter__(self):
value = self.start
if self.step > 0:
while value < self.stop:
yield value
value += self.step
else:
while value > self.stop:
yield value
value += self.step

def __len__(self):
return self._len

def __repr__(self):
if self.step == 1:
return 'Range(, )'.format(self.start, self.stop)
return 'Range(, , )'.format(self.start, self.stop, self.step)

def __reversed__(self):
return iter(self[::-1])

def _index(self, value):
index_mul_step = value - self.start
if index_mul_step % self.step:
return -1
index = index_mul_step // self.step
if 0 <= index < self._len:
return index
return -1

def count(self, value):
"""
Rangeobject.count(value) -> integer
Return number of occurrences of value.
"""
return sum(1 for n in self if n == value)

def index(self, value, start=0, stop=None):
"""
Rangeobject.index(value, [start, [stop]]) -> integer
Return index of value.
Raise ValueError if the value is not present.
"""
if start < 0:
start = max(self._len + start, 0)
if stop is None:
stop = self._len
if stop < 0:
stop += self._len

if isinstance(value, numbers.Integral):
index = self._index(value)
if start <= index < stop:
return index
raise ValueError(' is not in Range'.format(value))

i = start
n = self.start + self.step * i
while i < stop:
if n == value:
return i
i += 1
n += self.step
raise ValueError(' is not in Range'.format(value))


collections.abc.Sequence.register(Range)


test_pyrange.py



# pylint: disable = too-few-public-methods

import itertools

from pyrange import Range


class Equal:
def __eq__(self, other):
return True


class Indexable:
def __init__(self, n):
self.n = n

def __index__(self):
return self.n


def test_basic():
small_builtin_range = range(10)
small_my_range = Range(10)
equal = Equal()
assert small_builtin_range.count(equal) == small_my_range.count(equal) == 10
assert small_my_range.index(equal) == small_my_range.index(equal) == 0

big_my_range = Range(0, 10 ** 20, 10 ** 5)
assert 10 ** 15 in big_my_range
assert big_my_range[Indexable(10 ** 3)] == 10 ** 8
assert big_my_range[
Indexable(10 ** 3):Indexable(10 ** 6):Indexable(10 ** 2)
] == Range(10 ** 8, 10 ** 11, 10 ** 7)


def test_slicing():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for slice_start, slice_stop, slice_step in itertools.product(
list(range(-3, 3)) + [None], repeat=3
):
if slice_step == 0:
continue
slc = slice(slice_start, slice_stop, slice_step)
builtin_range_slice = builtin_range[slc]
my_range_slice = my_range[slc]
for name in ('start', 'stop', 'step'):
assert (
getattr(builtin_range_slice, name) ==
getattr(my_range_slice, name)
), (start, stop, step, slice_start, slice_stop, slice_step)


def test_eq_and_hash():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for start_2, stop_2, step_2 in itertools.product(
range(-3, 3), repeat=3
):
if step_2 == 0:
continue
builtin_range_2 = range(start_2, stop_2, step_2)
my_range_2 = Range(start_2, stop_2, step_2)
if builtin_range == builtin_range_2:
assert my_range == my_range_2, (
start, stop, step, start_2, stop_2, step_2
)
assert hash(my_range) == hash(my_range_2), (
start, stop, step, start_2, stop_2, step_2
)









share|improve this question









New contributor



sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$




I implemented class Range as an equivalent to Python built-in range for practicing purposes. No features were added. Hope it mimics all aspects of range behavior, but maybe you can point out something I forgot. Also I tried to make the code efficient, that's why Range doesn't inherit from collections.abc.Sequence and doesn't use any of it's not abstract methods. All feedback on how to improve the code is welcome!



pyrange.py



"""
Pure Python implementation of built-in range
"""


import math
import collections.abc
import numbers


def interpret_as_integer(obj):
if hasattr(obj, '__index__'):
return obj.__index__()
raise TypeError(
''' object cannot be interpreted as an integer'.format(
type(obj).__name__
)
)


def adjust_indices(length, start, stop, step):
if step is None:
step = 1
else:
step = interpret_as_integer(step)

if start is None:
start = length - 1 if step < 0 else 0
else:
start = interpret_as_integer(start)
if start < 0:
start += length
if start < 0:
start = -1 if step < 0 else 0
elif start >= length:
start = length - 1 if step < 0 else length

if stop is None:
stop = -1 if step < 0 else length
else:
stop = interpret_as_integer(stop)
if stop < 0:
stop += length
if stop < 0:
stop = -1 if step < 0 else 0
elif stop >= length:
stop = length - 1 if step < 0 else length

return start, stop, step


class Range:
"""
Range(stop) -> Range object
Range(start, stop[, step]) -> Range object

Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. Range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! Range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
"""

__slots__ = ('start', 'stop', 'step', '_len')

def __init__(self, start, stop=None, step=1):
if stop is None:
start, stop = 0, start
self.start, self.stop, self.step = (
interpret_as_integer(obj) for obj in (start, stop, step)
)
if step == 0:
raise ValueError('Range() arg 3 must not be zero')
step_sign = int(math.copysign(1, self.step))
self._len = max(
1 + (self.stop - self.start - step_sign) // self.step, 0
)

def __contains__(self, value):
if isinstance(value, numbers.Integral):
return self._index(value) != -1
return any(n == value for n in self)

def __eq__(self, other):
if not isinstance(other, Range):
return False
if self._len != len(other):
return False
if self._len == 0:
return True
if self.start != other.start:
return False
if self[-1] == other[-1]:
return True
return False

def __getitem__(self, index):
if isinstance(index, slice):
start, stop, step = adjust_indices(
self._len, index.start, index.stop, index.step
)
return Range(
self.start + self.step * start,
self.start + self.step * stop,
self.step * step
)
index = interpret_as_integer(index)
if index < 0:
index += self._len
if not 0 <= index < self._len:
raise IndexError('Range object index out of Range')
return self.start + self.step * index

def __hash__(self):
if self._len == 0:
return id(Range)
return hash((self._len, self.start, self[-1]))

def __iter__(self):
value = self.start
if self.step > 0:
while value < self.stop:
yield value
value += self.step
else:
while value > self.stop:
yield value
value += self.step

def __len__(self):
return self._len

def __repr__(self):
if self.step == 1:
return 'Range(, )'.format(self.start, self.stop)
return 'Range(, , )'.format(self.start, self.stop, self.step)

def __reversed__(self):
return iter(self[::-1])

def _index(self, value):
index_mul_step = value - self.start
if index_mul_step % self.step:
return -1
index = index_mul_step // self.step
if 0 <= index < self._len:
return index
return -1

def count(self, value):
"""
Rangeobject.count(value) -> integer
Return number of occurrences of value.
"""
return sum(1 for n in self if n == value)

def index(self, value, start=0, stop=None):
"""
Rangeobject.index(value, [start, [stop]]) -> integer
Return index of value.
Raise ValueError if the value is not present.
"""
if start < 0:
start = max(self._len + start, 0)
if stop is None:
stop = self._len
if stop < 0:
stop += self._len

if isinstance(value, numbers.Integral):
index = self._index(value)
if start <= index < stop:
return index
raise ValueError(' is not in Range'.format(value))

i = start
n = self.start + self.step * i
while i < stop:
if n == value:
return i
i += 1
n += self.step
raise ValueError(' is not in Range'.format(value))


collections.abc.Sequence.register(Range)


test_pyrange.py



# pylint: disable = too-few-public-methods

import itertools

from pyrange import Range


class Equal:
def __eq__(self, other):
return True


class Indexable:
def __init__(self, n):
self.n = n

def __index__(self):
return self.n


def test_basic():
small_builtin_range = range(10)
small_my_range = Range(10)
equal = Equal()
assert small_builtin_range.count(equal) == small_my_range.count(equal) == 10
assert small_my_range.index(equal) == small_my_range.index(equal) == 0

big_my_range = Range(0, 10 ** 20, 10 ** 5)
assert 10 ** 15 in big_my_range
assert big_my_range[Indexable(10 ** 3)] == 10 ** 8
assert big_my_range[
Indexable(10 ** 3):Indexable(10 ** 6):Indexable(10 ** 2)
] == Range(10 ** 8, 10 ** 11, 10 ** 7)


def test_slicing():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for slice_start, slice_stop, slice_step in itertools.product(
list(range(-3, 3)) + [None], repeat=3
):
if slice_step == 0:
continue
slc = slice(slice_start, slice_stop, slice_step)
builtin_range_slice = builtin_range[slc]
my_range_slice = my_range[slc]
for name in ('start', 'stop', 'step'):
assert (
getattr(builtin_range_slice, name) ==
getattr(my_range_slice, name)
), (start, stop, step, slice_start, slice_stop, slice_step)


def test_eq_and_hash():
for start, stop, step in itertools.product(range(-3, 3), repeat=3):
if step == 0:
continue
builtin_range = range(start, stop, step)
my_range = Range(start, stop, step)
for start_2, stop_2, step_2 in itertools.product(
range(-3, 3), repeat=3
):
if step_2 == 0:
continue
builtin_range_2 = range(start_2, stop_2, step_2)
my_range_2 = Range(start_2, stop_2, step_2)
if builtin_range == builtin_range_2:
assert my_range == my_range_2, (
start, stop, step, start_2, stop_2, step_2
)
assert hash(my_range) == hash(my_range_2), (
start, stop, step, start_2, stop_2, step_2
)






python reinventing-the-wheel interval






share|improve this question









New contributor



sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question









New contributor



sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question








edited 10 hours ago









dfhwze

11.7k2 gold badges22 silver badges77 bronze badges




11.7k2 gold badges22 silver badges77 bronze badges






New contributor



sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked 10 hours ago









sanyashsanyash

1414 bronze badges




1414 bronze badges




New contributor



sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




sanyash is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • $begingroup$
    Your constructor is __init__(start, stop=None, step=1). Shouldn't start be optional and stop positional? range(3) means [0, 1, 2], not [3, 4, 5, ...].
    $endgroup$
    – Jack M
    9 hours ago










  • $begingroup$
    @JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
    $endgroup$
    – sanyash
    9 hours ago
















  • $begingroup$
    Your constructor is __init__(start, stop=None, step=1). Shouldn't start be optional and stop positional? range(3) means [0, 1, 2], not [3, 4, 5, ...].
    $endgroup$
    – Jack M
    9 hours ago










  • $begingroup$
    @JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
    $endgroup$
    – sanyash
    9 hours ago















$begingroup$
Your constructor is __init__(start, stop=None, step=1). Shouldn't start be optional and stop positional? range(3) means [0, 1, 2], not [3, 4, 5, ...].
$endgroup$
– Jack M
9 hours ago




$begingroup$
Your constructor is __init__(start, stop=None, step=1). Shouldn't start be optional and stop positional? range(3) means [0, 1, 2], not [3, 4, 5, ...].
$endgroup$
– Jack M
9 hours ago












$begingroup$
@JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
$endgroup$
– sanyash
9 hours ago




$begingroup$
@JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
$endgroup$
– sanyash
9 hours ago










1 Answer
1






active

oldest

votes


















2














$begingroup$

It does not mimic all aspects of range. The range object is immutable:



>>> r = range(1,5,2)
>>> r.start
1
>>> r.start = 3
Traceback (most recent call last):
module __main__ line 130
traceback.print_exc()
module <module> line 1
r.start = 3
AttributeError: readonly attribute
>>>


Yours is not. But you might be able to fix that by inheriting from collections.namedtuple.






share|improve this answer









$endgroup$














  • $begingroup$
    Good point about immutability. However I don't think that inhertiting from collections.namedtuple is the best idea. Do you know another alternatives?
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    The are hacks to make objects immutable, such as here and here, but why are you opposed to inheriting from namedtuple?
    $endgroup$
    – AJNeufeld
    6 hours ago










  • $begingroup$
    Because logically Range has nothing common with namedtuple or tuple. range_obj[0] == range_obj.start but range_obj[1] != range_obj.stop in many cases and range_obj[2] != range_obj.step in many cases.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    Hmm. It seems I can’t subclass a namedtuple and overload the __getitem__ method to a different behaviour. How ... exceptional. Well, you’ve got the __setattr__ hack, so you can make your Range immutable that way.
    $endgroup$
    – AJNeufeld
    5 hours ago














Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);







sanyash is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded
















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229073%2fpure-python-range-implementation%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














$begingroup$

It does not mimic all aspects of range. The range object is immutable:



>>> r = range(1,5,2)
>>> r.start
1
>>> r.start = 3
Traceback (most recent call last):
module __main__ line 130
traceback.print_exc()
module <module> line 1
r.start = 3
AttributeError: readonly attribute
>>>


Yours is not. But you might be able to fix that by inheriting from collections.namedtuple.






share|improve this answer









$endgroup$














  • $begingroup$
    Good point about immutability. However I don't think that inhertiting from collections.namedtuple is the best idea. Do you know another alternatives?
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    The are hacks to make objects immutable, such as here and here, but why are you opposed to inheriting from namedtuple?
    $endgroup$
    – AJNeufeld
    6 hours ago










  • $begingroup$
    Because logically Range has nothing common with namedtuple or tuple. range_obj[0] == range_obj.start but range_obj[1] != range_obj.stop in many cases and range_obj[2] != range_obj.step in many cases.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    Hmm. It seems I can’t subclass a namedtuple and overload the __getitem__ method to a different behaviour. How ... exceptional. Well, you’ve got the __setattr__ hack, so you can make your Range immutable that way.
    $endgroup$
    – AJNeufeld
    5 hours ago
















2














$begingroup$

It does not mimic all aspects of range. The range object is immutable:



>>> r = range(1,5,2)
>>> r.start
1
>>> r.start = 3
Traceback (most recent call last):
module __main__ line 130
traceback.print_exc()
module <module> line 1
r.start = 3
AttributeError: readonly attribute
>>>


Yours is not. But you might be able to fix that by inheriting from collections.namedtuple.






share|improve this answer









$endgroup$














  • $begingroup$
    Good point about immutability. However I don't think that inhertiting from collections.namedtuple is the best idea. Do you know another alternatives?
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    The are hacks to make objects immutable, such as here and here, but why are you opposed to inheriting from namedtuple?
    $endgroup$
    – AJNeufeld
    6 hours ago










  • $begingroup$
    Because logically Range has nothing common with namedtuple or tuple. range_obj[0] == range_obj.start but range_obj[1] != range_obj.stop in many cases and range_obj[2] != range_obj.step in many cases.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    Hmm. It seems I can’t subclass a namedtuple and overload the __getitem__ method to a different behaviour. How ... exceptional. Well, you’ve got the __setattr__ hack, so you can make your Range immutable that way.
    $endgroup$
    – AJNeufeld
    5 hours ago














2














2










2







$begingroup$

It does not mimic all aspects of range. The range object is immutable:



>>> r = range(1,5,2)
>>> r.start
1
>>> r.start = 3
Traceback (most recent call last):
module __main__ line 130
traceback.print_exc()
module <module> line 1
r.start = 3
AttributeError: readonly attribute
>>>


Yours is not. But you might be able to fix that by inheriting from collections.namedtuple.






share|improve this answer









$endgroup$



It does not mimic all aspects of range. The range object is immutable:



>>> r = range(1,5,2)
>>> r.start
1
>>> r.start = 3
Traceback (most recent call last):
module __main__ line 130
traceback.print_exc()
module <module> line 1
r.start = 3
AttributeError: readonly attribute
>>>


Yours is not. But you might be able to fix that by inheriting from collections.namedtuple.







share|improve this answer












share|improve this answer



share|improve this answer










answered 6 hours ago









AJNeufeldAJNeufeld

12.1k1 gold badge11 silver badges37 bronze badges




12.1k1 gold badge11 silver badges37 bronze badges














  • $begingroup$
    Good point about immutability. However I don't think that inhertiting from collections.namedtuple is the best idea. Do you know another alternatives?
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    The are hacks to make objects immutable, such as here and here, but why are you opposed to inheriting from namedtuple?
    $endgroup$
    – AJNeufeld
    6 hours ago










  • $begingroup$
    Because logically Range has nothing common with namedtuple or tuple. range_obj[0] == range_obj.start but range_obj[1] != range_obj.stop in many cases and range_obj[2] != range_obj.step in many cases.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    Hmm. It seems I can’t subclass a namedtuple and overload the __getitem__ method to a different behaviour. How ... exceptional. Well, you’ve got the __setattr__ hack, so you can make your Range immutable that way.
    $endgroup$
    – AJNeufeld
    5 hours ago

















  • $begingroup$
    Good point about immutability. However I don't think that inhertiting from collections.namedtuple is the best idea. Do you know another alternatives?
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    The are hacks to make objects immutable, such as here and here, but why are you opposed to inheriting from namedtuple?
    $endgroup$
    – AJNeufeld
    6 hours ago










  • $begingroup$
    Because logically Range has nothing common with namedtuple or tuple. range_obj[0] == range_obj.start but range_obj[1] != range_obj.stop in many cases and range_obj[2] != range_obj.step in many cases.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    6 hours ago










  • $begingroup$
    Hmm. It seems I can’t subclass a namedtuple and overload the __getitem__ method to a different behaviour. How ... exceptional. Well, you’ve got the __setattr__ hack, so you can make your Range immutable that way.
    $endgroup$
    – AJNeufeld
    5 hours ago
















$begingroup$
Good point about immutability. However I don't think that inhertiting from collections.namedtuple is the best idea. Do you know another alternatives?
$endgroup$
– sanyash
6 hours ago




$begingroup$
Good point about immutability. However I don't think that inhertiting from collections.namedtuple is the best idea. Do you know another alternatives?
$endgroup$
– sanyash
6 hours ago












$begingroup$
The are hacks to make objects immutable, such as here and here, but why are you opposed to inheriting from namedtuple?
$endgroup$
– AJNeufeld
6 hours ago




$begingroup$
The are hacks to make objects immutable, such as here and here, but why are you opposed to inheriting from namedtuple?
$endgroup$
– AJNeufeld
6 hours ago












$begingroup$
Because logically Range has nothing common with namedtuple or tuple. range_obj[0] == range_obj.start but range_obj[1] != range_obj.stop in many cases and range_obj[2] != range_obj.step in many cases.
$endgroup$
– sanyash
6 hours ago




$begingroup$
Because logically Range has nothing common with namedtuple or tuple. range_obj[0] == range_obj.start but range_obj[1] != range_obj.stop in many cases and range_obj[2] != range_obj.step in many cases.
$endgroup$
– sanyash
6 hours ago












$begingroup$
As I see, hacking __setattr__ is the best way.
$endgroup$
– sanyash
6 hours ago




$begingroup$
As I see, hacking __setattr__ is the best way.
$endgroup$
– sanyash
6 hours ago












$begingroup$
Hmm. It seems I can’t subclass a namedtuple and overload the __getitem__ method to a different behaviour. How ... exceptional. Well, you’ve got the __setattr__ hack, so you can make your Range immutable that way.
$endgroup$
– AJNeufeld
5 hours ago





$begingroup$
Hmm. It seems I can’t subclass a namedtuple and overload the __getitem__ method to a different behaviour. How ... exceptional. Well, you’ve got the __setattr__ hack, so you can make your Range immutable that way.
$endgroup$
– AJNeufeld
5 hours ago












sanyash is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded

















sanyash is a new contributor. Be nice, and check out our Code of Conduct.












sanyash is a new contributor. Be nice, and check out our Code of Conduct.











sanyash is a new contributor. Be nice, and check out our Code of Conduct.














Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229073%2fpure-python-range-implementation%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її