[Python-ideas] List Revolution

ron3200 ron3200 at gmail.com
Sun Sep 11 06:52:50 CEST 2011

On Sun, 2011-09-11 at 11:51 +1000, Nick Coghlan wrote:
> On Sun, Sep 11, 2011 at 10:37 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> > 0-based indexes are useful for some tasks, and less useful for other tasks.
> > In my experience, I find that 0-based indexing is more useful most of the
> > time: it leads to fewer off-by-one errors.
> >
> > 1-based indexes are particularly well-suited for programming languages using
> > a natural language metaphor, usually aimed at non-programmers. Examples
> > include Xion, Applescript, and Inform-7.
> Indeed, the concepts of half-open ranges and 0-based indexing go hand
> in hand (as described in the EWD article), and it ties directly in to
> the notion of *index arithmetic*.
> A case that illustrates this nicely is that of partitioning a
> sequence. Suppose we want the first 5 items in one subsequence and the
> rest in another. This is easy to write, and requires no adjustments to
> the numbers:
>   head = seq[:5]
>   assert len(head) == 5
>   tail = seq[5:]
>   assert len(tail) == len(seq) - 5
> Zero based indexing (in conjunction with half-open ranges) makes the
> arithmetic work out nicely, and, in practice, that turns out to be
> important when it comes to writing correct programs.
> However, it comes at the cost of breaking the intuitive mapping to the
> counting numbers: the first item is at offset 0, the second is at
> offset 1, etc. This is a definite downside, but the collective
> judgment of many language designers is that the reduction in
> off-by-one errors when manipulating indices is worth the additional
> difficulty in learning the language for programming novices.

Python slicing was designed with indexing in mind.  If we had used
counts instead, we could have just added a bit of syntax to make things
work in a nice way.

The biggest difference isn't the math, but having a way to specify
weather a count, is inclusive or exclusive.  Given that, the math will
work just as nice.

(note: using '...' instead of ':' to make it clear it's different.)   

    head = seq[...n]        # the first n items
    tail = seq[n>...]       # items after first n items
    assert len(head) = n
    assert len(head) + len(tail) = len(seq)

And the reverse works too.

    tail = seq[-n...]      # the last n items
    head = seq[...<-n]     # items before the last n items

    assert len(tail) == n
    assert len(head) + len(tail) == len(seq)

And then you also have.

   before = seq[...<n]
   item   = seq[n]
   after  = seq[n>...]

And while we're at it.

   inner = seq[n1...n2]    # items from n1 to n2, including n2
   inner = seq[n1>...<n2]  # items after n1, and before n2

   outer = seq[...<n>...]  # everything but item n

   thewholething = seq[...]

Adding items to the front and back.

   seq[...<1] = seq      # prepend items
   seq[-1>...] = seq     # append items


So it can be done either way.  It's just not good to try and mix index's
with counts.  (Not suggesting we do this, but if we were starting from
scratch, I don't see any problems with it.)



More information about the Python-ideas mailing list