code: def normalize_range(e, n):
      
      if e.step > 0:
          count = max(0, (e.stop - e.start - 1) // e.step + 1)
      else:
          count = max(0, (e.start - e.stop - 1) // -e.step + 1)
  
      if count == 0:
          return (0, 0, e.step)
  
      start = e.start
      finish = e.start + (count - 1) * e.step
      if start >= 0:
          if start >= n or finish < 0 or finish >= n:
              return None
      else:
          start += n
          finish += n
          if start < 0 or start >= n or finish < 0 or finish >= n:
              return None
      assert count >= 0
      return (start, count, e.step)
docs: Return the range tuple normalized for an ``n``-element object.
  
      The semantics of a range  is slightly different than that of a slice.
      In particular, a range is similar to a list in meaning (and on Py2 it was
      eagerly expanded into a list). Thus we do not allow the range to generate
      indices that would be invalid for an ``n``-array. Furthermore, we restrict
      the range to produce only positive or only negative indices. For example,
      ``range(2, -2, -1)`` expands into ``[2, 1, 0, -1]``, and it is confusing
      to treat the last "-1" as the last element in the list.
  
      :param e: a range object representing a selector
      :param n: number of elements in a sequence to which ``e`` is applied
      :returns: tuple ``(start, count, step)`` derived from ``e``, or None
          if the range is invalid.