On Thu, Apr 17, 2014 at 01:28:19PM -0500, Ryan Hiebert wrote:
On Thu, Apr 17, 2014 at 1:12 PM, Terry Reedy
wrote: Range gives you a lot for free, including slicing.
I have wondered why Python has both slice and range, given the power that range has. Is there anything that slice can do that range can't, or are there some functional differences?
Because one is screwdriver and the other is a spanner? (Just don't ask me which one is which :-) But seriously, while they have similar signatures, they are semantically very different. range objects are concrete interators that produce numeric values, and all three arguments must be integers: py> range(2, 3, None) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'NoneType' object cannot be interpreted as an integer while slices are an extremely generic, type-agnostic mechanism for pointing to multiple indexes of some sequence: py> slice("spam", 2.5, 17) slice('spam', 2.5, 17) Slices have no meaning of their own, it's up to the sliced object to interpret them. The above slice will raise TypeError when used on a list, but may be accepted happily by some other custom sequence type. As far as built-in objects go, slices with negative indexes, or with end=None, can't be interpreted as indexes until you know which sequence they are applied to: range(1, 6, 2) always yields 1, 3, 5. slice(1, 6, 2) always refers to indexes 1, 3, 5. but range(1, -6, 2) is always empty. slice(1, -6, 2) may be empty, or it could refer to index 1 alone, or to indexes 1, 3, or indexes 1, 3, 5, or 1, 3, 5, 7, or ... In general, you cannot tell what indexes the slice will cover until you know what sequence it has been applied to. Built-in lists and tuples allow slices to extend past the ends of the sequence. That concept is meaningless with range. So despite the fact that slice() and range() have similar signatures, they are used differently, and have very different semantics. -- Steven