From 0e73124949d364003ded3b4966fa11dd404288b9 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 3 May 2024 11:37:32 -0500 Subject: [PATCH 1/4] gh-118476: Fix corner cases in islice() rough equivalent. --- Doc/library/itertools.rst | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 9a5cb8be37d3496..9ffa431706b6724 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -496,7 +496,8 @@ loops that truncate the stream. data where the internal structure has been flattened (for example, a multi-line report may list a name field on every third line). - Roughly equivalent to:: + Rough equivalent without error checking for negative indices or *step* + size of zero:: def islice(iterable, *args): # islice('ABCDEFG', 2) → A B @@ -504,24 +505,13 @@ loops that truncate the stream. # islice('ABCDEFG', 2, None) → C D E F G # islice('ABCDEFG', 0, None, 2) → A C E G s = slice(*args) - start, stop, step = s.start or 0, s.stop or sys.maxsize, s.step or 1 - it = iter(range(start, stop, step)) - try: - nexti = next(it) - except StopIteration: - # Consume *iterable* up to the *start* position. - for i, element in zip(range(start), iterable): - pass - return - try: - for i, element in enumerate(iterable): - if i == nexti: - yield element - nexti = next(it) - except StopIteration: - # Consume to *stop*. - for i, element in zip(range(i + 1, stop), iterable): - pass + start, stop, step = s.start or 0, s.stop, s.step or 1 + indices = count() if stop is None else range(max(stop, start)) + nexti = start + for i, element in zip(indices, iterable): + if i == nexti: + yield element + nexti += step .. function:: pairwise(iterable) From 09f779d3bc999c3bb421c574144e0f0e038e9013 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 3 May 2024 11:38:40 -0500 Subject: [PATCH 2/4] Grammar fix --- Doc/library/itertools.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 9ffa431706b6724..54bda06b340a539 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -496,7 +496,7 @@ loops that truncate the stream. data where the internal structure has been flattened (for example, a multi-line report may list a name field on every third line). - Rough equivalent without error checking for negative indices or *step* + Rough equivalent without error checking for negative indices or a *step* size of zero:: def islice(iterable, *args): From 74e03c91c8cc255953fb3d1017e0b80418c5aad2 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 3 May 2024 12:55:50 -0500 Subject: [PATCH 3/4] Improve argument checking --- Doc/library/itertools.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 54bda06b340a539..25859d7197ea378 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -496,8 +496,7 @@ loops that truncate the stream. data where the internal structure has been flattened (for example, a multi-line report may list a name field on every third line). - Rough equivalent without error checking for negative indices or a *step* - size of zero:: + Roughly equivalent to:: def islice(iterable, *args): # islice('ABCDEFG', 2) → A B @@ -505,7 +504,11 @@ loops that truncate the stream. # islice('ABCDEFG', 2, None) → C D E F G # islice('ABCDEFG', 0, None, 2) → A C E G s = slice(*args) - start, stop, step = s.start or 0, s.stop, s.step or 1 + start = 0 if s.start is None else s.start + stop = s.stop + step = 1 if s.step is None else s.step + if start < 0 or (stop is not None and stop < 0) or step <= 0: + raise ValueError indices = count() if stop is None else range(max(stop, start)) nexti = start for i, element in zip(indices, iterable): From 7bc98b8026fbc127ebcc850e6a7e198d01ffe74c Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 3 May 2024 15:31:33 -0500 Subject: [PATCH 4/4] Improve variable name --- Doc/library/itertools.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 25859d7197ea378..8d946d01db379f3 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -510,11 +510,11 @@ loops that truncate the stream. if start < 0 or (stop is not None and stop < 0) or step <= 0: raise ValueError indices = count() if stop is None else range(max(stop, start)) - nexti = start + next_i = start for i, element in zip(indices, iterable): - if i == nexti: + if i == next_i: yield element - nexti += step + next_i += step .. function:: pairwise(iterable)