bpo-27212: Modify islice recipe to consume initial values preceding s… · python/cpython@c8698cf
@@ -1172,6 +1172,7 @@ def test_islice(self):
11721172 (10, 20, 3),
11731173 (10, 3, 20),
11741174 (10, 20),
1175+ (10, 10),
11751176 (10, 3),
11761177 (20,)
11771178 ]:
@@ -1198,6 +1199,10 @@ def test_islice(self):
11981199self.assertEqual(list(islice(it, 3)), list(range(3)))
11991200self.assertEqual(list(it), list(range(3, 10)))
120012011202+it = iter(range(10))
1203+self.assertEqual(list(islice(it, 3, 3)), [])
1204+self.assertEqual(list(it), list(range(3, 10)))
1205+12011206# Test invalid arguments
12021207ra = range(10)
12031208self.assertRaises(TypeError, islice, ra)
@@ -1571,6 +1576,48 @@ def test_takewhile(self):
15711576self.assertEqual(list(takewhile(lambda x: x<5, [1,4,6,4,1])), [1,4])
15721577157315781579+class TestPurePythonRoughEquivalents(unittest.TestCase):
1580+1581+@staticmethod
1582+def islice(iterable, *args):
1583+s = slice(*args)
1584+start, stop, step = s.start or 0, s.stop or sys.maxsize, s.step or 1
1585+it = iter(range(start, stop, step))
1586+try:
1587+nexti = next(it)
1588+except StopIteration:
1589+# Consume *iterable* up to the *start* position.
1590+for i, element in zip(range(start), iterable):
1591+pass
1592+return
1593+try:
1594+for i, element in enumerate(iterable):
1595+if i == nexti:
1596+yield element
1597+nexti = next(it)
1598+except StopIteration:
1599+# Consume to *stop*.
1600+for i, element in zip(range(i + 1, stop), iterable):
1601+pass
1602+1603+def test_islice_recipe(self):
1604+self.assertEqual(list(self.islice('ABCDEFG', 2)), list('AB'))
1605+self.assertEqual(list(self.islice('ABCDEFG', 2, 4)), list('CD'))
1606+self.assertEqual(list(self.islice('ABCDEFG', 2, None)), list('CDEFG'))
1607+self.assertEqual(list(self.islice('ABCDEFG', 0, None, 2)), list('ACEG'))
1608+# Test items consumed.
1609+it = iter(range(10))
1610+self.assertEqual(list(self.islice(it, 3)), list(range(3)))
1611+self.assertEqual(list(it), list(range(3, 10)))
1612+it = iter(range(10))
1613+self.assertEqual(list(self.islice(it, 3, 3)), [])
1614+self.assertEqual(list(it), list(range(3, 10)))
1615+# Test that slice finishes in predictable state.
1616+c = count()
1617+self.assertEqual(list(self.islice(c, 1, 3, 50)), [1])
1618+self.assertEqual(next(c), 3)
1619+1620+15741621class TestGC(unittest.TestCase):
1575162215761623def makecycle(self, iterator, container):
@@ -2125,6 +2172,17 @@ def test_permutations_sizeof(self):
21252172... "Return function(0), function(1), ..."
21262173... return map(function, count(start))
212721742175+>>> import collections
2176+>>> def consume(iterator, n=None):
2177+... "Advance the iterator n-steps ahead. If n is None, consume entirely."
2178+... # Use functions that consume iterators at C speed.
2179+... if n is None:
2180+... # feed the entire iterator into a zero-length deque
2181+... collections.deque(iterator, maxlen=0)
2182+... else:
2183+... # advance to the empty slice starting at position n
2184+... next(islice(iterator, n, n), None)
2185+21282186>>> def nth(iterable, n, default=None):
21292187... "Returns the nth item or a default value"
21302188... return next(islice(iterable, n, None), default)
@@ -2265,6 +2323,14 @@ def test_permutations_sizeof(self):
22652323>>> list(islice(tabulate(lambda x: 2*x), 4))
22662324[0, 2, 4, 6]
226723252326+>>> it = iter(range(10))
2327+>>> consume(it, 3)
2328+>>> next(it)
2329+3
2330+>>> consume(it)
2331+>>> next(it, 'Done')
2332+'Done'
2333+22682334>>> nth('abcde', 3)
22692335'd'
22702336@@ -2353,6 +2419,7 @@ def test_main(verbose=None):
23532419test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,
23542420RegressionTests, LengthTransparency,
23552421SubclassWithKwargsTest, TestExamples,
2422+TestPurePythonRoughEquivalents,
23562423SizeofTest)
23572424support.run_unittest(*test_classes)
23582425