5

If s is a slice object in Python, constructed using either s = slice(start, stop, step) or (in the appropriate context) start:stop:step, the values used to construct s are available from the slice object itself as s.start, s.stop and s.step.

Similar start, stop and step members are available on range objects in Python 3.4 [Issue9896]. For example, range(1, 4, 2).start == 1.

However, Python 2.7 xrange objects do not have the start, stop and step members. Is there any other way to obtain the values used to construct the xrange from the object itself?

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
user200783
  • 13,722
  • 12
  • 69
  • 135
  • You can pretty easily get values that would construct an equivalent range, but not the actual constructor arguments used. – user2357112 Apr 21 '15 at 09:25

2 Answers2

4

It is possible to recover the original start and step arguments, but not always the original stop argument.

One way you can get the values is to look at the __reduce__ (or __reduce_ex__) method of the xrange object (normally used for pickling):

>>> x = xrange(10)
>>> x.__reduce__()[1]
(0, 10, 1)
>>> y = xrange(2, 100, 13)
>>> y.__reduce__()[1]
(2, 106, 13)

Then start, stop, step = y.__reduce__()[1] would assign the three variable names to the appropriate integers. The start and step values are always the original values that were used to construct the xrange object.

stop may be higher that the argument originally used to contract the object. For any xrange object x it is equal to x[-1] + step.

In general, it is not possible to recover the original stop argument once the xrange object has been created. If you study the source for xrange, you'll see that this object does not keep a reference to a particular stop value, only the starting value, step value and overall length of the iterator. When str or __reduce__ is called, the object will calculate the latest possible stop value with the internal function get_stop_for_range.

This is in contrast to Python 3's range object, which does remember the original stop value.

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
3

It's not pretty, but you could parse the str representation of the xrange

>>> rr = xrange(1, 4, 2)
>>> str(rr)
'xrange(1, 5, 2)'
>>> start = str(rr).split('(')[1].split(',')[0]
>>> start
1

etc

Note that the max cannot reliably be found this way if there are steps specified in the range. For example, in the example above, (1, 4, 2) becomes (1, 5, 2) in the str representation.

jlb83
  • 1,988
  • 1
  • 19
  • 30