# Arithmetic sequences in Python

Tom Anderson twic at urchin.earth.li
Tue Jan 17 19:06:57 EST 2006

```On Tue, 17 Jan 2006, Antoon Pardon wrote:

> Op 2006-01-16, Alex Martelli schreef <aleax at mail.comcast.net>:
>> Paul Rubin <http://phr.cx@NOSPAM.invalid> wrote:
>>
>>> Steven D'Aprano <steve at REMOVETHIScyber.com.au> writes:
>>>> solutions like range and xrange.
>>>
>>> Oh come on, [5,4,..0] is much easier to read than range(5,-1,-1).
>>
>> But not easier than reversed(range(6)) [[the 5 in one of the two
>> expressions in your sentence has to be an offbyone;-)]]
>
> Why don't we give slices more functionality and use them.
> These are a number of ideas I had. (These are python3k ideas)
>
> 1) Make slices iterables. (No more need for (x)range)
>
> 2) Use a bottom and stop variable as default for the start and
>   stop attribute. top would be a value that is greater than
>   any other value, bottom would be a value smaller than any
>   other value.
>
> 3) Allow slice notation to be used anywhere a value can be
>   used.
>
> 4) Provide a number of extra operators on slices.
>   __neg__ (reverses the slice)
>   __and__ gives the intersection of two slices
>   __or__ gives the union of two slices
>
> 5) Provide sequences with a range (or slice) method.
>   This would provide an iterator that iterates over
>   the indexes of the sequences. A slice could be
>   provided

+5

>  for i, el in enumerate(sequence):
>
> would become
>
>  for i in sequence.range():
>    el = sequence[i]

That one, i'm not so happy with - i quite like enumerate; it communicates
intention very clearly. I believe enumerate is implemented with iterators,
meaning it's potentially more efficient than your approach, too. And since
enumerate works on iterators, which yours doesn't, you have to keep it
anyway. Still, both would be possible, and it's a matter of taste.

> But the advantage is that this would still work when someone subclasses
> a list so that it start index is an other number but 0.

It would be possible to patch enumerate to do the right thing in those
situations - it could look for a range method on the enumerand, and if it
found one, use it to generate the indices. Like this:

def enumerate(thing):
if (hasattr(thing, "range")):
indices = thing.range()
else:
indices = itertools.count()
return itertools.izip(indices, thing)

> If you only wanted every other index one could do the following
>
>  for i in sequence.range(::2):
>
> which would be equivallent to
>
>  for i in sequence.range() & (::2):

Oh, that is nice. Still, you could also extend enumerate to take a range
as an optional second parameter and do this with it. Six of one, half a
dozen of the other, i suppose.

tom

--