What is an idiomatic and efficient way of obtaining a iterator equivalent of this slice?
obj[start:stop:step]
functionally equivalent to (I think) something like this:
def iter_slice(obj, start, stop, step=None):
length = len(obj)
range_step = 1 if step is None else step
range_start = ((0 if range_step > 0 else length - 1) if start is None
else start if start >= 0
else max(length + start, 0))
range_stop = ((length if range_step > 0 else -1) if stop is None
else min(stop, length) if stop >= 0
else length + stop)
for i in range(range_start, range_stop, range_step):
yield obj[i]
I am wondering if there is a way that can make use of either Python's builtin slicing capabilities or some library function, rather than have to try to handle all the cases explicitly (as I've attempted above, whether correctly or not).
There is some discussion here, but the answers all involve one of the following:
use of
itertools.islice
, but this doesn't support negative values, and also it is not an efficient way to iterate over a slice with a largestart
orstep
where indexing is possible insteadexplicitly creating a slice in memory in order to iterate over it, rather than iterating over the original object
use of some simple expression for the arguments to
range
, which works for non-negative numbers that are in range, but is not easily generalised to cover all the cases
Is there a concise way that avoids these issues?