Skip to content

Slicing strings

3 min read

A Telebirr message tells you what you paid, but the amount is buried in a sentence. By the end of this lesson you'll cut exactly the piece you need out of a string, reverse a string, and know why slicing past the end never crashes.

A slice takes what's there

In lesson 1.3, "Selam"[5] was an IndexError: there is no position 5. Predict this one, which asks for positions 1 to 100.

What will this print?

Decide before you look. Guessing wrong is how this sticks.

print("Selam"[1:100])
Pick the output

Python prints

elam

A slice takes the characters from 1 up to 100 that exist, and stops quietly at the end. Only a single index has to exist.

You met the in lesson 4.1 with lists, and it works the same on strings. text[start:stop] begins at position and ends just before position . Like every string method, a slice returns a new string; the original never changes.

An index points at one character, so that character has to exist. A slice is a range, and Python gives you whatever part of the range exists, even nothing:

name = "Selam"
print(name[1:100])
print(name[-3:])
print(repr(name[10:]))

In the editor, press Escape then Tab to move on.

name[-3:] is the last three characters. name[10:] starts past the end, so it's the , ''. That's why repr is there: print alone would show a blank line.

Positions must be whole numbers, which bites when you cut a string in half:

Steps, and reversing

A slice can have a third number. Predict this, with both numbers left out and a -1 at the end:

What will this print?

Decide before you look. Guessing wrong is how this sticks.

print("Selam"[::-1])
Pick the output

Python prints

maleS

The third number is the step. -1 walks backwards, one character at a time, from the end to the start: the whole string reversed.

If you said m, you read it as [-1], the last character. If you said Sela, you read it as [:-1], a stop of -1: everything before the last character. Count the colons: two of them means the -1 is a third number.

The third number is the : how far to move each time. [::2] takes every second character, from the start.

name = "Selam"
print(name[::2])
print(name[1::2])
print(name[::-1])

In the editor, press Escape then Tab to move on.

Change name to your own name and run it again.

Quick check

What is "Mawj"[::-1]?

A word that reads the same both ways is a palindrome. With [::-1], checking one is a single comparison (and lower() from lesson 6.1, so the capital H doesn't count):

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

print(is_palindrome("level"))
print(is_palindrome("Hannah"))
print(is_palindrome("Selam"))

In the editor, press Escape then Tab to move on.

Cutting a piece out of a message

Here's a made-up payment message. The amount sits between ETB and the next space. You don't know its position in advance, so find gets it for you. find takes a second argument, the position to start searching from, which finds "the next space after the amount". Step through it:

Step through it

Press Next to run one line at a time and watch each name change.

sms = "Paid ETB 250.00 to Selam Coffee"
start = sms.find("ETB ") + 4
end = sms.find(" ", start)
amount = sms[start:end]
print(amount)
Names and their values after line 1
NameValue after line 1
sms'Paid ETB 250.00 to Selam Coffee'new
startnot made yet
endnot made yet
amountnot made yet

Output so far

Step 1 of 5

Step 1 of 5. Line 1: sms = "Paid ETB 250.00 to Selam Coffee". sms is now 'Paid ETB 250.00 to Selam Coffee'.

Line 2: ETB starts at 5, and it's 4 characters long, so the amount starts at 9. Line 3: the first space from 9 on is at 15. Line 4: the slice takes positions 9 to 14. The Mawj bot reads payment messages in much the same way.

There's a trap. If ETB isn't in the message, find returns -1, and nothing stops the program:

Exercise

The transaction ID

Cut the transaction ID out of this made-up message. It comes after ID: and ends at the next full stop. Use find and a slice, not the ID's position counted by hand.

Output
DF12GH34

Your code

sms = "You paid ETB 250.00 to Selam Coffee. Transaction ID: DF12GH34. Thank you."
# Find where the ID starts and ends, then slice

In the editor, press Escape then Tab to move on.

Show a solution

This is one way to solve it, not the only one. If yours prints the same thing, it works.

sms = "You paid ETB 250.00 to Selam Coffee. Transaction ID: DF12GH34. Thank you."
start = sms.find("ID: ") + 4
end = sms.find(".", start)
print(sms[start:end])

Key takeaways

  • A slice text[start:stop] takes from start up to, not including, stop, and returns a new string.
  • An index must exist; a slice never raises for going past the end. It gives what's there, even ''.
  • The step is the third number: [::2] takes every second character, [::-1] reverses.
  • find(text, start) searches from start; with slicing, it cuts a piece out of a message. Check for -1 first.