Pure python range implementationPython implementation of SHA1ECDH implementation in pythonLSB steganography...

Why is belonging not transitive?

Delete empty subfolders, keep parent folder

Floating Point XOR

Transit visa to Hong Kong

Latex matrix formatting

Is there a generally agreed upon solution to Bradley's Infinite Regress without appeal to Paraconsistent Logic?

Why is the return value of the fun function 8 instead of 7?

Which version of the Pigeonhole principle is correct? One is far stronger than the other

How to ensure that neurotic or annoying characters don't get tiring on the long run

Statistical tests for benchmark comparison

Is my sink P-trap too low?

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

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

Is there a theorem in Real analysis similar to Cauchy's theorem in Complex analysis?

Travel distance across water in early prehistory

Neta Revai is achzareyos?

Is it possible that the shadow of the moon is a single dot during solar eclipse?

What does the Free Recovery sign (UK) actually mean?

Should I inform my future product owner that there are big chances that a team member will leave the company soon?

Random restarts for unsatisfiable problems

Test to know when to use GLM over Linear Regression?

Is it acceptable to use decoupling capacitor ground pad as ground for oscilloscope probe?

how to know this integral finite or infinite

What are the typical trumpet parts in classical music?



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;
}







7












$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
    7 hours ago










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


















7












$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
    7 hours ago










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














7












7








7





$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 8 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 8 hours ago









sanyashsanyash

1364 bronze badges




1364 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
    7 hours ago










  • $begingroup$
    @JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
    $endgroup$
    – sanyash
    7 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
    7 hours ago










  • $begingroup$
    @JackM in case of Range(3) there are lines if stop is None: start, stop = 0, start.
    $endgroup$
    – sanyash
    7 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
7 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
7 hours ago












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




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










1 Answer
1






active

oldest

votes


















1














$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
    4 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
    4 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
    3 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    3 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
    3 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









1














$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
    4 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
    4 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
    3 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    3 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
    3 hours ago


















1














$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
    4 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
    4 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
    3 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    3 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
    3 hours ago
















1














1










1







$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 4 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
    4 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
    4 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
    3 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    3 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
    3 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
    4 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
    4 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
    3 hours ago










  • $begingroup$
    As I see, hacking __setattr__ is the best way.
    $endgroup$
    – sanyash
    3 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
    3 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
4 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
4 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
4 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
4 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
3 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
3 hours ago












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




$begingroup$
As I see, hacking __setattr__ is the best way.
$endgroup$
– sanyash
3 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
3 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
3 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

Taj Mahal Inhaltsverzeichnis Aufbau | Geschichte | 350-Jahr-Feier | Heutige Bedeutung | Siehe auch |...

Baia Sprie Cuprins Etimologie | Istorie | Demografie | Politică și administrație | Arii naturale...

Nicolae Petrescu-Găină Cuprins Biografie | Opera | In memoriam | Varia | Controverse, incertitudini...