Session 6 · Indexing and slicing#

📖 Based on the blog post Python: Indexing & Slicing.

The big idea#

A string is a row of characters, and each one has a position number: its index. Indexing picks one item; slicing cuts out a piece. The same rules work on lists and tuples, so you’ll use this in every session from here on.

Everyday example: seats in a cinema row. “Seat 3” is indexing. “Seats 3 to 6” is slicing.

Indexes and a slice of "HELLOWORLD" Each character has a positive index from the left (starting at 0) and a negative index from the right (starting at -1). message[3:7] takes indexes 3, 4, 5 and 6: the stop index is not included. H 0 -10 E 1 -9 L 2 -8 L 3 -7 O 4 -6 W 5 -5 O 6 -4 R 7 -3 L 8 -2 D 9 -1 + − message[3:7] → "LOWO"
Each character has a positive index from the left (starting at 0) and a negative index from the right (starting at -1). message[3:7] takes indexes 3, 4, 5 and 6: the stop index is not included.

Indexing: one character#

Python counts from 0:

word = "Python"
print(word[0], word[1], word[5])
P y n

Negative indexes count from the end: -1 is the last item.

word = "Python"
print(word[-1], word[-2], word[-6])
n o P

Going past the end raises an error: word[6] → IndexError: string index out of range.

Example: the initials of a name.

full_name = "Parotta Salna"
print(full_name[0] + full_name[8])
PS

Slicing: a piece#

text[start:stop] takes from start up to but not including stop:

text = "Hello, World!"
print(text[0:5])
print(text[7:12])
Hello
World

Tip

Why is stop excluded? So that stop - start is the length of the slice, and text[:5] + text[5:] gives back the whole string with no overlap.

Leaving out start or stop#

text = "Python Programming"
print(text[:6])      # from the beginning
print(text[7:])      # to the end
print(text[-3:])     # the last three characters
print(text[:-1])     # everything except the last
Python
Programming
ing
Python Programmin

Adding a step#

text[start:stop:step] takes every step-th character. A negative step goes backwards:

text = "abcdefghij"
print(text[::2])      # every second character
print(text[0:10:3])   # every third
print(text[::-1])     # reversed
print(text[::-2])     # reversed, every second
acegi
adgj
jihgfedcba
jhfdb

Real-world slicing#

filename = "report.pdf"
print(filename[-3:])                 # file extension

date = "20230722"                    # YYYYMMDD
print(f"Year: {date[:4]}, Month: {date[4:6]}, Day: {date[6:]}")

quote = "To be or not to be, that is the question."
print(quote[9:18])

print("Malayalam".lower() == "Malayalam".lower()[::-1])   # palindrome check
pdf
Year: 2023, Month: 07, Day: 22
not to be
True

Note

The blog post used quote[9:17], which gives 'not to b': the stop index is excluded, so it has to be one past the last e, which is 18.

Strings can’t be changed#

word = "Python"
# word[0] = "J"           → TypeError: 'str' object does not support item assignment
new_word = "J" + word[1:]  # build a new string instead
print(new_word)
Jython

Common mistakes#

  • Starting from 1. The first character is [0].

  • Expecting stop to be included. "Hello"[0:4] is "Hell".

  • Out-of-range index vs slice. "abc"[10] raises IndexError, but "abc"[1:10] is just "bc". Slices never complain.

  • filename[-3:] for extensions. It breaks for .jpeg or .py. Use filename.rsplit(".", 1)[-1] for any length.

Hands-on exercises#

Exercise 1 · First and last. For city = "Coimbatore", print the first letter, the last letter and the length.

Solution
city = "Coimbatore"
print(city[0], city[-1], len(city))     # C e 10

Exercise 2 · Middle character. Print the middle character of "Python" and of "Chennai" (for even lengths, the right-hand one of the middle two).

Solution
for word in ["Python", "Chennai"]:
    print(word[len(word) // 2])     # h, n

Exercise 3 · Palindrome. Write is_palindrome(word), ignoring case. Test “Madam”, “Level” and “Python”.

Solution
def is_palindrome(word):
    w = word.lower()
    return w == w[::-1]

for w in ["Madam", "Level", "Python"]:
    print(w, is_palindrome(w))     # True True False

Exercise 4 · Hide the card. Print a card number "1234567812345678" as ************5678.

Solution
card = "1234567812345678"
print("*" * (len(card) - 4) + card[-4:])

Exercise 5 · Dates. Turn "2024-07-15" into "15/07/2024" using only slicing.

Solution
d = "2024-07-15"
print(d[8:] + "/" + d[5:7] + "/" + d[:4])     # 15/07/2024

Exercise 6 · Every other word. For "one two three four five six", print every other word (one three five), using split() and a slice.

Solution
words = "one two three four five six".split()
print(" ".join(words[::2]))

The same slicing rules work on lists.