Pebellslearn by building
0%
RoadmapMatrixCatalogSandboxSign in
Fundamentals  ›  Lesson

Working with Strings

Working with Strings 16 minSlicing, methods, and formatting text
You're building a piece ofBill Splitter & Tip Calculator
This piece — receipt_header(): The header line printed at the top of every receipt.
Scenario A guest scrawls the venue name with odd spacing and caps. The receipt's top line must always read cleanly, like 'Cafe Python — Table 12'.
Your task
Build receipt_header(restaurant, table). It tidies up a venue name and returns the receipt's top line as 'Restaurant — Table N'. Example: receipt_header("cafe python", 12) → "Cafe Python — Table 12".

Working with Strings

Every receipt in our Bill Splitter is text. The venue name, the table label, the line that reads Cafe Python — Table 12 — all of it strings. And guests hand us messy input: stray spaces, RANDOM capitals, names typed in a hurry.

So this lesson is a cleaning kit. By the end you'll take " cafe python " and a table number and turn them into a header worth printing.


Characters have positions

A string is a sequence of characters, and each one sits at a numbered position called an index. Counting starts at 0, not 1 — the first character is s[0].

python

Negative indexes count backwards from the end, which saves you from doing arithmetic with len(). -1 is the last character.

python

Slices take a range

s[start:stop] grabs several characters at once. Here's the part that trips everybody up on their first day, so let's find out before I tell you:

What does this print?
print("Cafe Python"[1:4])

That asymmetry looks arbitrary, but it has a payoff: the length of a slice is always stop - start, and s[:3] + s[3:] rebuilds the original exactly. Leave a side blank to mean "all the way to that end."

python

Watch the slice actually walk the string. Step through it and keep an eye on piece as each line runs:

step through it
1s = "Cafe Python"
2first = s[:4]
3second = s[5:]
4piece = first + " & " + second
5print(piece)

Try it: change s[5:] to s[5:9] and step through again. Predict what second becomes before you press Play.


Cleaning up messy input

Real input arrives dirty. Three methods do almost all the work: .strip() drops whitespace from both ends, .replace() swaps text, and the case methods fix capitalisation.

python

For capitalisation you have four choices, and picking the right one matters:

python

.title() is the one our receipt wants: it capitalises the first letter of every word and lowercases the rest, so "THE GRILL" and "the grill" both come out as "The Grill".

It has a quirk worth meeting now rather than in production:

What does this print?
print("o'brien".title())

Strings never change

This is the idea that causes the most confusion, so let's hit it directly. String methods do not edit the string. They can't. They build a brand-new string and hand it back.

That means a method call on its own line accomplishes precisely nothing:

What does this print?
name = "  cafe  "
name.strip()
print(f"[{name}]")

Here's the same trap as running code. Fix it so it prints the cleaned name:

broken — fix it

This should print [cafe python] with no stray spaces — but it doesn't. Run it, then fix it.

And because a string can't be edited in place, changing one character isn't allowed either:

broken — fix itTypeError

Run this and read the error. Python is telling you something true about strings. Then make it print Kafe.

Reassigning the variable is fine — s = "K" + s[1:] works. It's reaching inside the characters that Python refuses.


Splitting and joining

.split() breaks a string into a list of pieces. .join() glues a list back into one string. They're mirror images, and you'll reach for them constantly.

python

The string you call .join() on is the glue that goes between the pieces — that's the bit people get backwards. With no argument at all, .split() breaks on any run of whitespace, which makes counting words a one-liner:

What does this print?
print(len("a b  c".split()))

f-strings put values into text

An f-string (note the f before the quote) drops values straight into text inside { }. After a colon you can add a format spec that controls how the value looks:

python

You can call methods inside the braces, which means the whole receipt header is one tidy expression:

python

Step through that one to see the cleaning happen in stages:

step through it
1restaurant = " cafe python "
2table = 12
3cleaned = restaurant.strip()
4titled = cleaned.title()
5header = f"{titled} — Table {table}"
6print(header)

Two details worth noticing. The between the name and the table is an em dash, a longer character than a hyphen. And an f-string always produces a string: f"{price:.2f}" gives you the text "16.80" — the number price itself is untouched.


🎯 Your turn

Write receipt_header(restaurant, table) — the tidy line at the top of every receipt:

  • receipt_header("cafe python", 12)"Cafe Python — Table 12"
  • receipt_header("THE GRILL", 8)"The Grill — Table 8"

Hint — clean the name with restaurant.strip().title(), then build the line with an f-string: f"{...} — Table {table}" (that dash is an em dash, —).

Then press ▶ Run, tap the Live App try chips, and hit ✓ Check. Green = this piece of the app is built. ✅

receipt_header.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
receipt_header(restaurant, table) → strThe tidy header line at the top of the receipt.
try:
returned
Press Run to execute your code.
Press Check to run the tests for this lesson.
Working with Strings — Pebells