Accessing String Characters in Python: How String Indexing Works
A string is more than a chunk of text — it's an ordered sequence of individual characters. Python gives every character a numbered position called an index, letting you pull out any single character with one line of code. This is the foundation of string parsing, text processing, and a huge range of coding interview problems.
Zero-Based Indexing: Every Character Has a Position
Python numbers positions starting at 0. The first character is index 0, the second is index 1, and so on. Use square brackets to access any character:
message = "Hello world!"
# 0123456789...
print(message[0]) # H (first character)
print(message[1]) # e
print(message[4]) # o
print(message[5]) # ' ' (space — all characters count, including spaces!)
print(message[6]) # w
print(message[11]) # ! (last character)
Spaces, punctuation, and every other character between the quotes all have their own index. There are no exceptions.
Negative Indexing: Count From the End
Negative indices let you count backwards from the end of the string — no need to know the length:
message = "Hello world!"
print(message[-1]) # ! (last character)
print(message[-2]) # d (second to last)
print(message[-6]) # w (sixth from the end)
Using Indexed Characters in Real Code
# Extract initials from a full name:
full_name = "Marie Curie"
# 0123456...
initials = full_name[0] + full_name[6]
print(initials) # MC
# Check if a string starts with a capital letter:
word = "Python"
if word[0] == word[0].upper():
print(f"'{word}' starts with a capital letter")
# Get the file extension from a filename:
filename = "report.pdf"
extension = filename[-3:] # slice from third-to-last to end
print(extension) # pdf
String Slicing: Extract a Substring
Slicing grabs a range of characters. The syntax is string[start:stop] — includes start, excludes stop:
phrase = "Hello world!"
print(phrase[0:5]) # Hello (indices 0-4)
print(phrase[6:11]) # world (indices 6-10)
print(phrase[:5]) # Hello (from start to index 4)
print(phrase[6:]) # world! (from index 6 to end)
print(phrase[::-1]) # !dlrow olleH (reversed)
Strings Are Immutable
An important distinction from lists: you cannot change a character by assigning to an index. Strings are immutable — each "modification" creates a new string:
word = "hello"
# This raises a TypeError:
# word[0] = "H" # TypeError: 'str' object does not support item assignment
# Correct way — build a new string:
word = "H" + word[1:]
print(word) # Hello
Common Mistakes to Avoid
- IndexError — index out of range: A string of 5 characters has valid indices 0–4. Accessing index 5 crashes.
- Off-by-one: Forgetting that indexing starts at 0 is the single most common string bug.
- Forgetting spaces have indices: Spaces are characters too — they count in the index sequence.
s = "abc" # indices: a=0, b=1, c=2
# Safe access:
if len(s) > 3:
print(s[3])
else:
print("Index 3 doesn't exist") # This runs
Key Takeaways
- Every character in a string has an index, starting at 0.
- Access any character with
string[index]; use negative indices to count from the end. - Slice a range of characters with
string[start:stop]. - Strings are immutable — indexing reads, it doesn't write.
What to Learn Next
With character access mastered, explore Python's powerful string methods: .upper(), .lower(), .split(), .replace(), and .find(). These let you transform and search strings without manually indexing every character.
