Slicing behavior of python range()[:] Slicing behavior of python range()[:] python python

Slicing behavior of python range()[:]


For a moment let's pretend that range still returned a list. Slicing the range object returns a range object which would act as if you were slicing the underlying list. Instead of doing this with a list though, the range object is able to take care of it in constant time using arithmetic.

>>> range(0, 90, 2)[10:23]range(20, 46, 2)>>> list(range(0, 90, 2)[10:23])[20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44]

When you do something like:

range(0, 10, 3)[:]

Python slices it with arithmetic.

My assumption is that when determining the final element it rounds up. It tries to compute the zeroth element in the range to start with. This will be start + step * 0 = 0.

Then Python tries to get the ending element. There are (10 - 0) // 3 + 1 = 4 elements in the range, so the ending element is start + step * n_elements = 0 + 3 * 4 = 12.


I think a few things are mixed here.

  • range produces slicing behavior, because slicing with non-default indexes makes sense:
>>> list(range(10, 20)[3:7])[13, 14, 15, 16]
  • There is an idiom of copying a list (which is mutable) by producing a slice with all default indexes: some_list[:] is equivalent to something like [x for x in some_list].
  • There is the strange code that does [:] for the range object (or the actual list, if it's Python 2) which makes no sense. The generated range object / list is not referenced anywhere else anyway.
  • Python documentation lists slicing among "Common Sequence Operations" in a chapter named "Sequence Types — list, tuple, range" (emph. mine). So it's documented, but few people ever read it.