Working with text — indexing, slicing, and f-strings
Pulling pieces out of text, cleaning it, changing it, and building readable messages with f-strings — plus the rule that text cannot be modified in place.
- 1Encounter
- 2Understand
- 3Worked
- 4Predict
- 5Apply
- 6Stretch
The problem we are solving
A name arrives from a form: " Rafi Ahmed ". Extra spaces at both ends, and what you need is the first name only, plus a message — "Welcome, Rafi!".
That work — cleaning text, pulling pieces out of it, and building something new from them — is among the most frequent tasks in programming. Usernames, email addresses, ids, filenames, addresses, whatever an API sends back: all text.
And one more thing will become clear today, the kind that costs hours when you do not know it: in Python, text cannot be modified. Writing name.upper() does not make name uppercase. Why not, and what to do instead, is the most valuable part of this mission.
By the end of this mission you can
- Reach any character by index, from the front and from the back
- Cut a section out with a slice
- Clean and change text with
strip,upper,lower,replaceandsplit - Explain why the result of a method has to be kept
- Build readable messages with f-strings
Prerequisites: Variables and types.
Quotes — one or two
To Python, 'Rafi' and "Rafi" are the same thing. Both exist so that quotes inside the text cause no trouble:
print("It's working")
print('She said "yes"')It's working
She said "yes"Three quotes hold text that spans several lines:
note = """Dear customer,
Your order is confirmed.
Thank you."""
print(note)Dear customer,
Your order is confirmed.
Thank you.And \n produces a new line, \t a tab:
print("Name:\tRafi\nRole:\tLearner")Name: Rafi
Role: LearnerLength and index
word = "PYTHON"
print(len(word))
print(word[0])
print(word[1])
print(word[-1])
print(word[-2])6
P
Y
N
OTwo things to fix in your head:
Counting starts at zero. The first character is index 0, the second 1. So in a six-character word the last index is 5, not 6. Ask for word[6] and you get an IndexError. This "one too many" mistake is so common it has its own name: an off-by-one error.
Negative indexes count from the back. word[-1] is the last character, word[-2] the one before. It is the easy way to reach the end without knowing the length.
Slices — cutting a section out
word = "PROGRAMMING"
print(word[0:7])
print(word[7:11])
print(word[:7])
print(word[7:])
print(word[-4:])PROGRAM
MING
PROGRAM
MING
MINGword[a:b] means from a up to but not including b. The end index is left out.
That feels awkward at first, and it buys you something: word[0:7] and word[7:11] join up exactly, with no character repeated and none missed. Leaving out the first number means "from the very beginning", and leaving out the second means "all the way to the end".
Text cannot be modified
This is the most important rule in the mission:
name = "rafi"
name[0] = "R"TypeError: 'str' object does not support item assignmentA character inside existing text cannot be swapped out. So how does uppercasing or trimming work at all? The answer: Python does not change the original, it builds a new piece of text and hands it back.
name = " rafi "
print(name.strip())
print(name.strip().upper())
print("After all that, name is still:", name)rafi
RAFI
After all that, name is still: rafiname did not change at all. strip() produced a new, clean piece of text, and we merely printed it — we never stored it.
So you have to keep the result:
name = " rafi "
clean_name = name.strip().upper()
print(clean_name)RAFIOr assign it back to the same name — name = name.strip(). This one mistake, calling a method and dropping the result, happens to everybody early on. And it raises no error, which is why it takes a while to spot.
The methods that earn their keep
raw = " Rafi Ahmed "
print(raw.strip())
print(raw.strip().lower())
print(raw.strip().upper())
print(raw.strip().replace(" ", "_"))
print(len(raw), len(raw.strip()))
print("rafi" in raw.lower())Rafi Ahmed
rafi ahmed
RAFI AHMED
Rafi_Ahmed
14 10
Truestrip()— trims whitespace at the start and end (not in the middle)lower()/upper()— changes casereplace(a, b)— putsbeverywhereaappearedin— says whether one piece of text occurs inside another
And split() breaks text into pieces:
full_name = "Rafi Ahmed Khan"
parts = full_name.split(" ")
print(parts)
print(parts[0])
print(len(parts))['Rafi', 'Ahmed', 'Khan']
Rafi
3The thing in square brackets is a list, which has a mission of its own. For now just know that split() returns the pieces that way, and that an index gets one piece out.
Clean before you compare. If a user types"Rafi ", that is not equal to"rafi"— a trailing space and a capital letter make three differences between them. Which is why running.strip().lower()before comparing is close to a universal habit in real projects.
f-strings — the easy way to build a message
Mixing text and numbers has been clumsy so far. An f-string makes it simple: an f before the quote, and anything you like inside braces:
name = "Rafi"
items = 3
price = 12.5
print(f"Hello, {name}!")
print(f"{items} items cost {items * price}")
print(f"Rounded: {items * price:.2f}")Hello, Rafi!
3 items cost 37.5
Rounded: 37.50Notice three benefits: you can calculate inside the braces (items * price), you never think about types (numbers become text on their own), and :.2f pins the number of decimal places — which every display of a monetary figure needs.
Have a look at what happens when the f is forgotten:
name = "Rafi"
print("Hello, {name}")Hello, {name}No error, just a wrong message. Having seen it once makes it easy to catch later.
A complete example
account.py:
# Turn a raw form entry into a clean display name and a login id
raw_input_name = " Rafi Ahmed "
domain = "example.com"
clean = raw_input_name.strip()
parts = clean.split(" ")
first_name = parts[0]
last_name = parts[-1]
login_id = f"{first_name.lower()}.{last_name.lower()}"
email = f"{login_id}@{domain}"
initials = f"{first_name[0]}{last_name[0]}"
print(f"Display name : {clean}")
print(f"Login id : {login_id}")
print(f"Email : {email}")
print(f"Initials : {initials}")
print(f"Name length : {len(clean)} characters")Display name : Rafi Ahmed
Login id : rafi.ahmed
Email : rafi.ahmed@example.com
Initials : RA
Name length : 10 charactersWhy parts[-1]? Because someone's name may have three parts. Taking the last piece from the back works whether there are two parts or three.
When it breaks
IndexError: string index out of range The index you asked for is past the end of the text. Remember that if len(word) is 6, the valid indexes are 0 to 5. For the last character, word[-1] is the safest thing to write.
TypeError: 'str' object does not support item assignment You tried to change one character inside text. That is not possible — build new text instead, e.g. word = "R" + word[1:].
I called the method and nothing changed The result was not stored anywhere. name.strip() does not change name; you need name = name.strip().
strip() is not removing the spaces in the middle strip() only works at the two ends. To remove the inner ones use replace(" ", "").
The f-string message comes out wrong Check for the f immediately before the quote. Without it, braces are printed as ordinary characters.
NameError — the name inside the f-string is unknown Whatever you wrote inside the braces was never created, or is misspelled.
Step 4 of 6 — Predict
Check your understanding
What is the output of these four lines?
word = "PYTHON"
print(word[0])
print(word[-1])
print(word[1:4])- AP N YTH
- BP N YTHO
- CP O YTH
- DY N YTHO
The intent was to print Hello, RAFI!, but the name comes out lowercase and still padded with spaces. Why?
name = " rafi "
name.strip()
name.upper()
print(f"Hello, {name}!")- A`strip()` and `upper()` do not change the original — they return new text, so the result has to be assigned back to `name`
- BA method can only be called once on a piece of text, not twice
- CAn f-string cannot show the result of a method
- D`strip()` cannot be called before `upper()`; the order has to be reversed
What does this f-string print?
item = "pen"
qty = 3
price = 12.5
print(f"{qty} x {item} = {qty * price:.2f}")- A3 x pen = 37.50
- B3 x pen = 37.5
- C{qty} x {item} = {qty * price}
- D3 x pen = 3 * 12.5
Answering needs an account
Sign in to check your answers
The questions are above, and working them out in your head is the part that matters. Sign in to see the answers, the explanations and the three-level hints.
Your turn
Write a file called slug.py that turns a title into a form suitable for a web address.
Starting value: title = " Learn Python Step By Step "
The output should be:
Title : Learn Python Step By Step
Slug : learn-python-step-by-step
Slug length: 25Four conditions:
- Trim the extra spaces at both ends
- Lowercase everything
- Replace the inner spaces with dashes
- Print all three lines with f-strings
Then do one extra thing: change title to " Python for Beginners " and run it. If the new title comes out right without you touching the code, it means you wrote a real calculation instead of typing the answers in by hand.
There is more in this mission
What you read above is the complete mission — nothing was cut out of it. Pro adds:
- What actually happens underneath — how Python runs this
- The full solution to the exercise, worked step by step
- Harder extra exercises
- The interview question on this topic, with a model answer
Step 6 of 6
Stretch — the chapter quiz
Ten questions from easy to hard. The last ones are difficult on purpose.
Sign in to take the quiz