Unit 08 · lesson
Strings Are Data Structures Too
Core path: 30 minutes
You already know strings as text. What changes when you start treating the text as an ordered sequence?
A string is not one indivisible blob to Python. It is an ordered sequence of characters.
That means characters have positions, slices can select ranges, loops can visit characters one at a time, and invalid positions can fail.
Position starts at zero
Take:
callsign = "NOVA"
The characters are ordered:
character: N O V A
index: 0 1 2 3
So:
print(callsign[0])
produces:
N
and:
print(callsign[3])
produces:
A
The first position is index 0, not 1.
That one rule creates a lot of beginner off-by-one bugs because humans usually count the first item as "one."
Length and last index are related, but not equal
word = "PYTHON"
print(len(word))
Output:
6
There are six characters.
The valid indexes are:
0 1 2 3 4 5
So the last index is:
len(word) - 1
not:
len(word)
This fails:
print(word[6])
because there is no character at index 6.
Python raises IndexError because the requested position is outside the sequence.
Slicing selects a range between boundaries
word = "ROBOTNIX"
print(word[0:5])
produces:
ROBOT
The slice syntax is:
[start:stop]
The start index is included.
The stop index is excluded.
So 0:5 selects indexes:
0 1 2 3 4
and stops before index 5.
Move the slice boundaries
Python includes the start index and excludes the stop index. Change both values and watch the selected characters update.
Try 0:5, 2:8, 3:3, and a start value greater than the stop value.
word[0:5]Selected indexes satisfy start ≤ index < stop. The stop boundary itself is never included.
Use the sequence explorer instead of memorizing the rule.
Try:
0:5
2:8
3:3
7:2
Before changing the controls, predict which characters should be highlighted.
For 3:3, there is no distance between the start and stop boundaries, so the result is an empty string.
For 7:2, the default forward slice direction cannot travel backward from start 7 to stop 2, so the result is also empty unless you explicitly use a negative step.
That is a useful reminder: slice boundaries describe a traversal, not just two random indexes.
Negative indexes count from the end
Python also supports:
word = "ROBOTNIX"
print(word[-1])
which produces the last character:
X
Useful examples:
-1 → last item
-2 → second from last
Do not mix negative indexing into every beginner solution just because it is shorter. Use it when it makes the intent clearer.
Strings are immutable
This works:
name = "nova"
name = name.upper()
This does not:
name = "nova"
name[0] = "N"
Python strings cannot be changed character-by-character in place.
Methods such as:
lower()
upper()
strip()
replace()
produce new string values.
So:
name.upper()
by itself does not permanently change what name refers to.
If you want the transformed string later:
name = name.upper()
A loop can traverse the sequence without indexes
for character in "nova":
print(character)
Output:
n
o
v
a
You do not always need an index to process sequence items.
Use an index when position matters.
Use direct iteration when you mainly need each item.
That is a cleaner decision than automatically writing range(len(...)) for every loop.
Derive the index instead of guessing
callsign = "GHOST"
Before running anything:
length = 5
first index = 0
last index = 4
Now verify:
print(len(callsign))
print(callsign[len(callsign) - 1])
Then deliberately create:
print(callsign[len(callsign)])
Read the resulting IndexError.
The failure is not mysterious. Your calculated position was one step beyond the valid sequence.
Build three useful slices
Given:
filename = "robot_status.json"
Without searching the internet for the answer, use indexing/slicing/string methods to reason about:
- the first five characters;
- the final four characters;
- whether the filename ends with
.json.
Python has useful methods such as .endswith() that may be clearer than manually slicing every time. The point is to understand the sequence model well enough to choose the readable operation.
Carry the Week 5 loop model forward
This is the connection:
Week 5: loop over repeated values
Week 8: strings/lists provide ordered values to loop over
The loop did not change.
The thing being iterated over changed.
That is how programming concepts start combining instead of living in separate weeks.
Vocabulary lab
Flip the idea, not just the card
Explain the term before you reveal the back. Then compare your explanation with the definition, example, and warning.
Read all terms without animation
- Sequence
- An ordered collection whose items can be processed in a defined order. Example: A string is a sequence of characters. Do not confuse it with: A single scalar value with no sequence positions.
- Index
- A numeric position used to select one item from a sequence. Example: word[0] accesses the first character. Do not confuse it with: A dictionary key used as a semantic label.
- Zero-Based Indexing
- A position system in which the first item is index 0. Example: The first character of PYTHON is at index 0 and the sixth is at index 5. Do not confuse it with: Human ordinal counting that often begins at 1.
- Slice
- A selection of sequence items between start and stop boundaries, with the stop normally excluded. Example: word[0:5] selects indexes 0 through 4. Do not confuse it with: Selecting exactly one item with word[0].
- Immutable
- Unable to be modified in place after creation. Example: A Python string cannot replace one character with name[0] = 'N'. Do not confuse it with: A list, whose items can be replaced in place.