-
-
Notifications
You must be signed in to change notification settings - Fork 32.8k
Closed
Labels
docsDocumentation in the Doc dirDocumentation in the Doc dir
Description
Documentation
The itertools.islice
reference implementation in the docs is complex and also slightly incorrect. For reference it is here
def islice(iterable, *args):
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
This does not correctly handle stop == 0
, overwriting it to be sys.maxsize
and also assumes its input is an iterator, not any iterable.
It is also just hard to reason about. Instead I propose
def islice(iterable, *args):
s = slice(*args)
start = s.start if s.start is not None else 0
stop = s.stop
step = s.step if s.step is not None else 1
it = iter(iterable)
for _ in zip(range(start), it):
# Consume up to *start* position
pass
if stop is not None and stop <= start:
return
for i, element in enumerate(it, start):
if (i - start) % step == 0:
yield element
if stop is not None and i + 1 >= stop:
return
This matches islice
exactly for these inputs
for start in itertools.chain(range(6), [None]):
for stop in itertools.chain(range(6), [None]):
for step in itertools.chain(range(1, 6), [None]):
for r in [range(0), range(4)]:
it = iter(r)
myx = list(islice(it, start, stop, step))
myy = list(it)
it = iter(r)
pyx = list(itertools.islice(it, start, stop, step))
pyy = list(it)
msg = "ERR" if myx != pyx or myy != pyy else "ok"
print(
f"{msg}: {r=}, {start=}, {stop=}, {step=}, {myx=}, {pyx=}, {myy=}, {pyy=}"
)
Linked PRs
- gh-118476: update the example implementation for islice in docs #118466
- gh-118476: Fix corner cases in islice() rough equivalent. #118559
- [3.12] gh-118476: Fix corner cases in islice() rough equivalent. (Gh-118559) #118587
- [3.11] gh-118476: Fix corner cases in islice() rough equivalent. (Gh-118559) #118588
Privat33r-dev and pochmann3
Metadata
Metadata
Assignees
Labels
docsDocumentation in the Doc dirDocumentation in the Doc dir