9.4 String Indexing and Slicing
Positive and negative indexing, slicing with s[start:stop:step], why slicing never raises IndexError, extended slicing for reversal, and copying strings safely.
Indexing and Negative Indexing
Every character in a string has a position. Positive indices count from the left starting at 0; negative indices count from the right starting at -1 — useful for reaching the end of a string without knowing its length.
>>> s = "Programming"
>>> s[0], s[-1]
('P', 'g')
Slicing
Slicing extracts a sub-string using s[start:stop:step]. start is the index to begin at (inclusive), stop is the index to end before (exclusive), and step is the gap between characters taken. Any of the three can be omitted — start defaults to 0, stop defaults to the end of the string, step defaults to 1.
Positive indices count from the left; negative indices count from the right of the string "PYTHON".
>>> s = "Programming"
>>> s[2:5] # characters at index 2, 3, 4 -- stop is exclusive
'ogr'
>>> s[:4] # start defaults to 0
'Prog'
>>> s[4:] # stop defaults to end of string
'ramming'
>>> s[:] # both default -- a full copy-like slice
'Programming'
Slicing Never Raises IndexError
Unlike direct indexing (s[50], which raises IndexError if out of range), a slice with an out-of-range start or stop simply clamps to the available characters — or returns an empty string if the range doesn’t overlap the string at all. This makes slicing safe to use with indices that haven’t been bounds-checked.
>>> s = "Programming"
>>> s[2:100] # stop far beyond the end -- clamps, no error
'ogramming'
>>> s[100:200] # entirely out of range -- empty string, no error
''
Extended Slicing
Extended slicing adds the step argument. A step greater than 1 skips characters; a negative step walks backward, which is what makes s[::-1] the idiomatic way to reverse a string — see 9.9 String Algorithms.
>>> s = "Programming"
>>> s[::2] # every 2nd character, left to right
'Pormig'
>>> s[::-1] # negative step -- walks backward -> reverses the string
'gnimmargorP'
>>> s[5:1:-1] # explicit start/stop with a negative step
'argo'
Real-world examples — stripping a known suffix/prefix and pulling a fixed-width timestamp out of a log line:
>>> filename = "server_backup_2026.tar.gz"
>>> filename[:-7] # strip the 7-char '.tar.gz' suffix
'server_backup_2026'
>>> log_line = "2026-07-13T10:22:05Z INFO message here"
>>> log_line[:19] # fixed-width ISO timestamp
'2026-07-13T10:22:05'
Copying Strings
Because strings are immutable, Python doesn’t need to make a real copy when the whole string is sliced — CPython recognizes s[:] and simply returns the same object, which is safe precisely because that object can never be mutated.
>>> s = "Programming"
>>> s_copy = s[:]
>>> s_copy is s # CPython reuses the same object -- safe due to immutability
True
Quick Interview Answer
“Indexing uses
s[i], with negative indices counting from the end. Slicing,s[start:stop:step], extracts a sub-string —stopis exclusive, and unlike direct indexing, an out-of-range slice never raises; it just clamps or returns an empty string. A negative step walks backward, which is whys[::-1]is the idiomatic one-line string reversal — there’s no dedicated.reverse()method for strings the way there is for lists.”
Common Mistakes
- Expecting
s[stop]to be included in a slice —stopis always exclusive, sos[2:5]gets indices 2, 3, 4, not 5. - Assuming an out-of-range slice raises
IndexErrorlike direct indexing does — it silently clamps instead, which can mask a bug where the indices were wrong. - Trying
s.reverse()— strings have no such method; the idiom iss[::-1].
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form