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
Documentation
The
itertools.islicereference implementation in the docs is complex and also slightly incorrect. For reference it is hereThis does not correctly handle
stop == 0, overwriting it to besys.maxsizeand also assumes its input is an iterator, not any iterable.It is also just hard to reason about. Instead I propose
This matches
isliceexactly for these inputsLinked PRs