diff --git a/python3/koans/about_filter.py b/python3/koans/about_filter.py new file mode 100644 index 000000000..65bcab9f0 --- /dev/null +++ b/python3/koans/about_filter.py @@ -0,0 +1,54 @@ +from runner.koan import * + + +class AboutFilter(Koan): + """ + filter(lambda, iterable) is a builtin function that returns an iterator that contains only + the elements for which lambda(x) == True + """ + + def test_filter_returns_iterator(self): + """ + An iterator is an object that can be iterated over (with a loop) + """ + stay_positive = lambda x: x > 0 + + result = [] + for x in filter(stay_positive, [-1, 0, 1]): + result.append(x) + + self.assertEqual(__, result) + + def test_filter_with_function(self): + """ + The filter function should filter items based on the function passed to it + """ + less_than_zero = lambda x: x < 0 + test_list = [-3, -1, 0, 5] + self.assertEqual(__, list(filter(less_than_zero, test_list))) + + def test_filter_with_callable(self): + """ + The filter function can take any callable that returns a boolean + """ + test_list = [1, 2, 3, 4] + self.assertEqual(__, list(filter(self._filter_stuff, test_list))) + + def _filter_stuff(self, x): + return x % 2 == 0 + + def test_filter_none_function(self): + """ + If function is None, the identity function is assumed. + That is, all elements of iterable that are false are removed. + ie. list.remove(x) if not x + """ + self.assertEqual(__, list(filter(None, [True, False, True, False]))) + + def test_filter_without_filter(self): + """ + The filter function is just shorthand for a list comprehension + """ + greater_then_zero = lambda x: x > 0 + test_list = [-2, -1, 0, 1, 2] + self.assertEqual(__, [item for item in test_list if greater_then_zero(item)]) diff --git a/python3/koans/about_range.py b/python3/koans/about_range.py new file mode 100644 index 000000000..23c580e7d --- /dev/null +++ b/python3/koans/about_range.py @@ -0,0 +1,80 @@ +from runner.koan import * +import functools +import collections.abc + + +class AboutRange(Koan): + """ + range(stop) + range(start, stop[, step]) is a builtin function that returns an range object from start to stop by step. + """ + + def test_range_is_a_sequence(self): + + self.assertEqual(__, isinstance(range(1), collections.abc.Sequence)) + + def test_range_is_not_an_iterator(self): + + with self.assertRaises(__): + next(range(1)) # should raise a TypeError + + def test_range_can_be_an_iterator(self): + + iter_range = iter(range(1)) + + self.assertEqual(__, next(iter_range)) + + def test_range_can_iterate(self): + result = [] + for x in range(3): + result.append(x) + self.assertEqual(__, result) + + def test_range_can_have_a_length(self): + + self.assertEqual(__, len(range(5))) + + def test_range_starts_with_zero_by_default(self): + + self.assertEqual(__, range(1).start) + + def test_range_can_return_value_at_index(self): + + self.assertEqual(__, range(10).index(5)) + + def test_range_can_start_at_another_value(self): + + result = [] + for x in range(1, 4): + result.append(x) + + self.assertEqual(__, result) + + def test_range_can_step_by_value(self): + + result = [] + for x in range(0, 20, 5): + result.append(x) + + self.assertEqual(__, result) + + def test_range_can_go_negative(self): + + result = [] + for x in range(0, -5, -1): + result.append(x) + + self.assertEqual(__, result) + + def test_range_with_map(self): + + result = list(map(lambda x: x * 2, range(5))) + + self.assertEqual(__, result) + + def test_range_can_work_with_other_iterators(self): + + def factorial(n): + return functools.reduce(lambda x, total: x * total, range(1, n + 1)) + + self.assertEqual(__, factorial(2)) # 2!