1

Possible Duplicate:
The Python Slice Notation

I am confused with the way python subsequence selection works. suppose i have this following code:

>>> t = 'hi'
>>> t[:3]
'hi'
>>> t[3:]
''
>>> print t[:3] + t[3:]
hi
>>> print t[3]

Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
print t[3]
IndexError: string index out of range

please explain how this thing works in python

Community
  • 1
  • 1
Hemant
  • 619
  • 2
  • 6
  • 17
  • http://stackoverflow.com/questions/509211/the-python-slice-notation – Hoopdady Jan 31 '13 at 14:05
  • 1
    @Hoopdady: Exactly; the highest voted answer includes an explanation. – Martijn Pieters Jan 31 '13 at 14:06
  • 1
    http://docs.python.org/2/tutorial/introduction.html#strings – Ashwini Chaudhary Jan 31 '13 at 14:06
  • 4
    Your example seems wrong, and is definitely inconsistent. `t[3:]` should be the empty string, or if it isn't, `t[:3] + t[3:]` would be 'hihi'. –  Jan 31 '13 at 14:06
  • Your examples are incorrect; `t[3:]` is an empty string. – Martijn Pieters Jan 31 '13 at 14:06
  • When I try `print t[3:]` for this string in interactive mode (Python 2.7.3 on Windows) I get a string of length 0 returned, not the string 'hi' – chucksmash Jan 31 '13 at 14:07
  • 1
    Not only are the examples incorrect, they are not formatted at all like an actual Python session. The lines that start with `>>>`, in a real session, are what the user types, not what Python spits out. Plus, the output of `print` doesn't include the quotes. Really, you should just copy and paste the session, don't try to retype. – John Y Jan 31 '13 at 14:08
  • @ IamChuckB: yaa u are right.. sorry for that.. I copied it from python shell and copied it incorrectly. – Hemant Feb 01 '13 at 04:59
  • @ all others: I apologize for the wrong example.. :( I copied it wrong. I know the format too isnt correct. – Hemant Feb 01 '13 at 05:00

3 Answers3

2

Subsequence, or slice, notation is forgiving. t[:3] will get you a slice of t from the beginning up to the end or the third element, whichever comes first, t[3:] will get you a slice of t from the third element if it exists through the end. Direct indexing such as t[3] is not forgiving; the indexed element must exist or else you get an exception. With slices, if the end index is out of range, you get the whole original list, if the start index is out of range, you get an empty list.

Silas Ray
  • 25,682
  • 5
  • 48
  • 63
2

I always find it somewhat funny behavior of sequences that they allow slicing out of bounds. However, this is documented. Specifically in bullet point 4 which describes slicing of a sequence type:

The slice of s from i to j is defined as the sequence of items with index k such that i <= k < j. If i or j is greater than len(s), use len(s). If i is omitted or None, use 0. If j is omitted or None, use len(s). If i is greater than or equal to j, the slice is empty.

or bullet point 5 which describes slicing with the optional stride parameter:

The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). If i or j is greater than len(s), use len(s). If i or j are omitted or None, they become “end” values (which end depends on the sign of k). Note, k cannot be zero. If k is None, it is treated like 1

Note that if you look at point 3 (which describes s[index]), there is no corresponding transform of out-of-bounds indices to in-bounds-indices.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • +1 for the docs. It is a bit weird to get used to at first I guess, but it saves lots of messy headache (and breeding ground for bugs) of doing things like `t[:3 if len(t) > 3 else len(t)]` everywhere. – Silas Ray Jan 31 '13 at 14:14
  • @sr2222 -- You could just write it as `t[:min(3,len(t))]` which isn't nearly as bad as the conditional expression (IMHO) and it's explicit -- If they changed the behavior, you wouldn't be able to get an empty sequence when you asked for a sequence of length 3: `t[4:7]` which I consider to be a "breeding ground for bugs". But -- It is how it is. I suppose I'll live with it. – mgilson Jan 31 '13 at 14:18
  • I can see where you are coming from, I guess I just never thought of it as, "give me a sequence of length 3," so much as, "give me the chunk of this sequence that falls within this range." I think it's modeled more on a pseudo-bitwise operation; if you think of a list as the head of an infinite length binary value, a slice is a bitwise AND (with the slice being another infinite binary where only the sliced elements are `1`) truncated by the list's length. – Silas Ray Jan 31 '13 at 14:30
1

t[start:stop] prints all elements x with start <= x < stop. When some elements do not exist it simply does not print them.

t[index] on the other hand gives an error if there is no element at given index.

In your example only t[0]='h' and t[1]='i' exist which explaines your results.

print t[3:] should return nothing instead of 'hi' which is also the case at my python interpreter.