Treat text as data: pick out characters by index, cut out pieces with slices, measure with len() and clean up with string methods.
About 35 minBeginner4 exercisesFree
You will be able to
Read single characters from a string with positive and negative indexes
Cut out part of a string with a slice
Measure, join and repeat strings with len(), + and *
Clean text with strip(), lower(), upper(), title() and replace()
Explain why string methods return a new string instead of changing the original
Much of the data programs handle is text: customer names typed in a hurry, invoice references like INV2025-0381-RUH, phone numbers with spaces and dashes. Before you can use that text you usually need to pull out a part of it (the year from a reference, the first letter of a name) or clean it up (remove stray spaces, fix capital letters).
In this lesson you'll treat a string as what it really is: an ordered sequence of characters you can measure, slice and transform.
Indexing: one character at a time
Each character in a string has a position called its index. Indexes start at 0, not 1. Put the index in square brackets to read that character:
character
R
i
y
a
d
h
index
0
1
2
3
4
5
negative index
-6
-5
-4
-3
-2
-1
Negative indexes count from the end: -1 is always the last character, whatever the length.
Reading characters by position
city ="Riyadh"print(city[0])print(city[3])print(city[-1])print(len(city))
Try it: Change city to "Dammam" and predict each line before running it.
len(text) returns how many characters a string has — spaces and punctuation count. The last valid index is always len(text) - 1. Asking for a position that doesn't exist raises an IndexError:
There is no index 6 in a 6-character string
city ="Riyadh"print(len(city))print(city[6])
Try it: Change city[6] to city[5], then to city[-6].
Slicing: a piece of a string
A slicetext[start:stop] gives the characters from start up to but not includingstop. The number of characters you get is stop - start.
Leave out start to begin at the start: text[:3].
Leave out stop to go to the end: text[4:].
Negative numbers work too: text[-3:] is the last three characters.
Unlike indexing, slicing never raises an error for positions past the end — you get whatever is there, possibly an empty string.
Pulling fields out of a fixed-format reference
ref ="INV2025-0381-RUH"
prefix = ref[:3]
year = ref[3:7]
number = ref[8:12]
branch = ref[-3:]print(prefix, year, number, branch)print(ref[100:])
Try it: Write the indexes under each character on paper, then check that ref[3:7] covers exactly 2, 0, 2, 5.
Try it: Delete the last line so the program finishes cleanly.
String methods
A method is a function that belongs to a value; you call it with a dot: text.upper(). The ones you'll use constantly:
method
what it returns
example
upper()
all capitals
"jeddah".upper() → 'JEDDAH'
lower()
all lowercase
"SALES".lower() → 'sales'
title()
each word capitalised
"noura al-otaibi".title() → 'Noura Al-Otaibi'
strip()
spaces (and tabs/newlines) removed from both ends
" 42 ".strip() → '42'
replace(old, new)
every old swapped for new
"050-123".replace("-", "") → '050123'
Strings are immutable: they can never be changed. A method gives you back a new string and leaves the original alone. If you want to keep the result, assign it — often to the same name:
name =" hala "
name.strip()# result thrown away; name is unchanged
name = name.strip()# name now refers to 'hala'
Cleaning a messy product name by chaining methods
raw =" wireless MOUSE "print("["+ raw +"]",len(raw))
clean = raw.strip().lower().replace(" "," ")print("["+ clean +"]",len(clean))print(clean.title())print(raw)
Try it: Remove .strip() from the chain and see how the length and brackets change.
Methods can be chained because each one returns a string, and the next method is called on that result, left to right. The last line shows raw is untouched.
Guided practice · ●difficulty 1 of 5 · about 4 min
Make initials for a name badge
A conference prints initials on name badges. Read a first name and a last name, each with its own input() (no prompt text — the tests type the values for you).
Store the initials in a variable called initials: the first letter of each name in capitals, each followed by a dot. Then print initials.
People sometimes type extra spaces or lowercase letters. For inputs lina and haddad the program prints:
L.H.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Challenge · ●●difficulty 2 of 5 · about 7 min
Parse an invoice reference
A distributor's invoice references always have this layout:
INV2025-0381-RUH
INV, then a 4-digit year, a dash, a 4-digit invoice number, a dash, and a 3-letter branch code. Staff often paste references with spaces around them or in lowercase.
Read one reference with input() (no prompt text). Clean it (remove surrounding spaces, make it uppercase), then store the pieces as strings in year, number and branch and print:
Year: 2025
Number: 0381
Branch: RUH
Keep number as a string so the leading zero survives.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Debugging · ●●difficulty 2 of 5 · about 5 min
Fix the mailing-list name cleaner
A bakery's mailing-list program should tidy a customer's name before saving it. For the input mARIAM al-SAYED it should print:
Mailing name: Mariam Al-Sayed
Characters: 15
But it prints the name exactly as typed, spaces and odd capitals included, and the wrong character count. Fix the program. The cleaned name must end up in the variable name. (It reads the name with input(), no prompt text.)
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Edge cases · ●●●difficulty 3 of 5 · about 8 min
Mask a phone number
A delivery app shows customers' phone numbers to drivers with everything except the last four digits hidden by *.
Read a phone number with input() (no prompt text). People type it in different ways: 050 123 4567, 055-987-6543, with spaces around it. Then:
remove surrounding spaces, and remove every space and dash inside it,
build masked: one * for every digit except the last four, followed by the last four digits,
print masked.
For 050 123 4567 the program prints:
******4567
A number with only four digits has nothing to hide.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Summary
Indexes start at 0; negative indexes count from the end, so text[-1] is the last character.
text[start:stop] returns a new string from start up to, but not including, stop; either end can be left out.
len() counts characters; + joins strings and * repeats them.
upper(), lower(), title(), strip() and replace() return new strings — assign the result to keep it.