Python synergies in list addressing
Something I took from this Ian Bicking entry is that synergies and elegance don't just happen; someone usually worked hard to make it all come out neatly. Python lists have an interesting case of this; some apparently odd decisions in other places turn out to be needed to create useful (and error-avoiding) synergies.
Python lists (and sequences in general) are indexed from 0. Zero-based
indexing presents a problem, which can be succinctly stated as this:
list element indexes run from 0 to len(lst)-1. That -1 is ugly
and error prone.
So Python has quietly arranged things so that you never have to write it
(or +1, its kissing cousin), by making 'slice' addressing of lists and
range() end-exclusive asymmetric (instead of 'i:j' running from i
to j, it runs from i to j-1). This means:
range(len(lst))generates indexes that exactly cover the list, since they run from 0 tolen(lst)-1.lst[:len(lst)]is the entire list.- if
prefis at the start of the list,lst[len(pref):]is the list withprefremoved from the start. - if
sublstis inlststarting atpos,lst[:pos]is everything beforesublstandlst[pos + len(sublst):]is everything aftersublst. - if
sufis at the end oflst,lst[:-len(suf)]is the list withsufremoved from the end. - avoiding a subtler error,
lst[len(pref):]works even ifprefis zero length (althoughlst[:-len(suf)]does not; can't win them all).
All of these are straightforward expressions, with nary a stray -1
or +1 in sight and no chance for off by one errors. (Is it elegant
or does the asymmetry cancel out the lack of +1 and -1? That's in
the eye of the beholder, but I like it.)
Python is not the first language to notice this issue; Scheme's
substring is end-exclusive, for example. Other things duck the issue
by having their substring operation take a start and a length, instead
of a start and and end position.
(This entry's genesis came from comments made on AClosureConfusion.)
|
|