diff --git a/README.md b/README.md index 1422e2b..34e43fe 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -# PythonHW_Iterator_Generator \ No newline at end of file +### PythonHW_Iterator_Generator + +Contains Python 3 code for classes IteratorEnhancedRange and GeneratorEnhancedRange. + +Both work similar to standard Python range(int) function, except they are able work with float arguments. +Both classes require at least one argument. All arguments are positional: +start (default = 0), end (no default, required argument), step (default = 1). +One specified argument (x) is interpreted as (0, x, 1). +Two arguments are interpreted as start and end, respectively. diff --git a/RangeEnhancedIterator_Generator.py b/RangeEnhancedIterator_Generator.py new file mode 100644 index 0000000..b933d50 --- /dev/null +++ b/RangeEnhancedIterator_Generator.py @@ -0,0 +1,84 @@ +class IteratorEnhancedRange: + + def __init__(self, *args): + #Arguments are: start (default = 0), end (no default, required argument), step (default = 1) + self.args = args + for arg in args: + if not (type(arg) == int or type(arg) == float): + raise Exception("Arguments must be numeric") + if len(args) == 1: + self.start = 0 + self.end = self.args[0] + self.step = 1 + elif len(args) == 2: + self.start = self.args[0] + self.end = self.args[1] + self.step = 1 + elif len(args) == 3: + if self.args[2] == 0: + raise Exception("Unable to range with step = 0") + self.start = self.args[0] + self.end = self.args[1] + self.step = self.args[2] + else: + raise Exception("IteratorEnhancedRange requires at least one, but no more than three arguments") + self.startediter = False + + def __iter__(self): + return self + + def __next__(self): + if (self.step / abs(self.step)) * self.start >= (self.step / abs(self.step)) * self.end: + raise StopIteration + else: + if self.startediter is False: + self.startediter = True + return self.start + else: + if (self.step / abs(self.step)) * (self.start + self.step) >= (self.step / abs(self.step)) * self.end: + raise StopIteration + else: + self.start += self.step + return self.start + + def __call__(self): + return self + + +class GeneratorEnhancedRange: + + def __init__(self, *args): + #Arguments are: start (default = 0), end (no default, required argument), step (default = 1) + self.args = args + for arg in args: + if not (type(arg) == int or type(arg) == float): + raise Exception("Arguments must be numeric") + if len(args) == 1: + self.start = - 1 + self.end = self.args[0] + self.step = 1 + elif len(args) == 2: + self.start = self.args[0] - 1 + self.end = self.args[1] + self.step = 1 + elif len(args) == 3: + if self.args[2] == 0: + raise Exception("Unable to range with step = 0") + self.start = self.args[0] - self.args[2] + self.end = self.args[1] + self.step = self.args[2] + else: + raise Exception("GeneratorEnhancedRange requires at least one, but no more than three arguments") + self.startediter = False + + def __iter__(self): + return GeneratorEnhancedRange.gener(self) + + def gener(self): + while (self.step / abs(self.step)) * (self.start + self.step) < (self.step / abs(self.step)) * self.end: + self.start += self.step + yield self.start + + def __call__(self): + return self + diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/Tests_RangeEnhancedGenerator.py b/tests/Tests_RangeEnhancedGenerator.py new file mode 100644 index 0000000..e24ebba --- /dev/null +++ b/tests/Tests_RangeEnhancedGenerator.py @@ -0,0 +1,36 @@ +import unittest +from RangeEnhancedIterator_Generator import GeneratorEnhancedRange + + +class GeneratorTests(unittest.TestCase): + + def test_on_range_w_one_arg(self): + self.assertEqual([n for n in GeneratorEnhancedRange(2)], [0, 1]) + + def test_on_range_w_two_args(self): + self.assertEqual([n for n in GeneratorEnhancedRange(2, 5)], [2, 3, 4]) + + def test_on_range_w_three_args(self): + self.assertEqual([n for n in GeneratorEnhancedRange(2, 7, 2)], [2, 4, 6]) + + def test_on_nonnumeric_args(self): + with self.assertRaises(Exception, msg = "Arguments must be numeric"): + example = GeneratorEnhancedRange(5, "o", -1) + + def test_on_zero_step(self): + with self.assertRaises(Exception, msg = "Unable to range with step = 0"): + example = GeneratorEnhancedRange(5, 6, 0) + + def test_on_wrong_number_of_args(self): + with self.assertRaises(Exception, + msg = "GeneratorEnhancedRange requires at least one, but no more than three arguments"): + example = GeneratorEnhancedRange() + with self.assertRaises(Exception, + msg = "GeneratorEnhancedRange requires at least one, but no more than three arguments"): + example = GeneratorEnhancedRange(2, 7, 2, 0) + + +if __name__ == '__main__': + unittest.main() + + diff --git a/tests/Tests_RangeEnhancedIterator.py b/tests/Tests_RangeEnhancedIterator.py new file mode 100644 index 0000000..1a6e2d7 --- /dev/null +++ b/tests/Tests_RangeEnhancedIterator.py @@ -0,0 +1,49 @@ +import unittest +from RangeEnhancedIterator_Generator import IteratorEnhancedRange + + +class IteratorTests(unittest.TestCase): + + def test_on_range_w_one_arg(self): + example = IteratorEnhancedRange(2) + self.assertEqual(next(example), 0) + self.assertEqual(next(example), 1) + self.assertRaises(StopIteration, next, example) + + def test_on_range_w_two_args(self): + example = IteratorEnhancedRange(2,5) + self.assertEqual(next(example), 2) + self.assertEqual(next(example), 3) + self.assertEqual(next(example), 4) + self.assertRaises(StopIteration, next, example) + + def test_on_range_w_three_args(self): + example = IteratorEnhancedRange(2, 7, 2) + self.assertEqual(next(example), 2) + self.assertEqual(next(example), 4) + self.assertEqual(next(example), 6) + self.assertRaises(StopIteration, next, example) + + def test_on_nonnumeric_args(self): + with self.assertRaises(Exception, msg = "Arguments must be numeric"): + example = IteratorEnhancedRange(5, "o", -1) + + def test_on_zero_step(self): + with self.assertRaises(Exception, msg = "Unable to range with step = 0"): + example = IteratorEnhancedRange(5, 6, 0) + + def test_on_wrong_number_of_args(self): + with self.assertRaises(Exception, + msg = "IteratorEnhancedRange requires at least one, but no more than three arguments"): + example = IteratorEnhancedRange() + with self.assertRaises(Exception, + msg = "IteratorEnhancedRange requires at least one, but no more than three arguments"): + example = IteratorEnhancedRange(2, 7, 2, 0) + + def tearDown(self): + print ('Tear down called') + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +