[Jay Bloodworth <johnabloodwor...@gmail.com>] > Does anybody have a nice, student friendly explanation of the > "half-open" semantics of the range function and of slice notation? In > other words, why does the list created by range(0,10) contain 0 as an > element but not 10, and why does mylist[0:10] start with mylist[0] and > end with mylist[9]? If you're an experienced coder, these semantics make > sense in terms of the underlying implementation and the usual use of > these objects as iterators, but if lists are new to you the behavior can > seem a little mysterious. Thoughts?
It's easiest to picture sequence indices as pointing _between_ sequence items rather than _at_ them. That's why there are N+1 meaningfully different indices into a sequence with N items. For example, for sequence A B C: 0 A 1 B 2 C 3 Now, e.g., "it's obvious" that 1:3 spans B and C, and 2:2 is an empty sequence. That slice lo:hi, with 0 <= lo <= hi and in bounds, yields a (sub)sequence with hi-lo elements, also prevents oodles of "off by 1" errors. It's just a convention that the non-slicing seq[i] notation refers to the sequence element "to the right" of i. It _could_ have referred to the one "to the left" instead, but "to the right' makes it consistent with C (all languages with 0-based array indexing). `range()` is related to this, but also driven by mathematical elegance. For lo <= k <= hi, list(range(lo:hi)) == list(range(lo:k)) + list(range(k:hi)) This is a very pleasant decomposition when, e.g,, developing inductive proofs of algorithm correctness as a loop marches over a sequence. When the loop index is i, at the start of the loop seq[0:i] has already been processed, and seq[i:] has yet to be done. No "off by 1" errors sneak in there either. _______________________________________________ Edu-sig mailing list -- edu-sig@python.org To unsubscribe send an email to edu-sig-le...@python.org https://mail.python.org/mailman3/lists/edu-sig.python.org/