Recall from lesson 1-3 that / and // behave differently. The type of 10 / 5 is float, because / always produces a float.
Even a division that comes out exactly even follows that rule, so 10 / 5 is 2.0 rather than 2. Getting a whole number requires 10 // 5, which gives the int 2. This distinction returns in unit 3, where values arriving from outside the program have to be converted before arithmetic works on them.
A string is a sequence of characters
Almost everything a program receives from the outside world arrives as a string: usernames, file names, dates, whole files. Pulling pieces out of them, the year from "2026-07-06", the extension from "report.pdf", is daily work for any engineer, and indexing and slicing are the tools that do it.
Every character in a string has a numbered position called an index. Counting starts at 0, not 1. You read one character with square brackets, and len() tells you how many characters there are.
word = "Python" # P y t h o n # 0 1 2 3 4 5
Negative indexes count from the end: word[-1] is the last character, word[-2] the one before it. That saves you from writing word[len(word) - 1].
Asking for an index that does not exist, like word[6] here, stops the program with an IndexError.
Reading single characters by index
Each line below picks one position out of the string, using the numbering from the diagram above.
word = "Python" print(len(word)) print(word[0]) print(word[5]) print(word[-1]) print(word[-2])
Output
6
P
n
n
oThe len call reports 6 characters, and because counting starts at 0 the valid indexes run from 0 to 5. Notice that word[5] and word[-1] print the same n: they are two ways of naming the final position, one counting forward from the start and one counting backward from the end.
Slicing: grabbing a piece
A slice copies a range of characters: word[start:stop] takes from index start up to but not including stop.
word = "Python" word[0:2] # "Py" indexes 0 and 1 word[2:6] # "thon"
Leave a side empty and Python fills in the edge: word[:2] means from the start, word[2:] means to the end. A handy way to read s[:n] is "the first n characters".
Slices never fail with an error. word[2:100] just stops at the end and gives "thon".
A pair of slices can split a string into two parts without any letters being retyped. The first slice takes everything up to index 3, and the second takes everything from index 3 onward.
s = "keyboard" print(s[:3]) print(s[3:])
Output
key board
The first three characters occupy indexes 0, 1, and 2, so s[:3] covers them, stopping just before index 3 as slices always do. Because s[3:] starts exactly where the first slice stopped, the two pieces fit together with nothing missing and nothing duplicated.
Slicing fields out of a date
Real data often packs several fields into one string, and slicing is how they come apart. In a date written YYYY-MM-DD the dashes occupy indexes 4 and 7, so each field is a slice that steps over them.
date = "2026-07-06" year = date[:4] month = date[5:7] day = date[8:] print(year) print(month) print(day)
Output
2026 07 06
Each slice is positioned around the separators. The year is date[:4], covering indexes 0 through 3 and stopping before the first dash. The month starts at index 5 to skip that dash and runs to date[5:7], stopping before the second one. The day is date[8:], which takes everything after the second dash without needing to know the string's length.