The order form arrives with ' MAYA chen ' and a trailing newline, because customers type the way they talk. Before any lookup can work, the text needs cleaning without being destroyed. Which methods return a new string, and how do you keep the original?
Real text arrives messy: extra spaces, mixed case, and fields packed into one string. String methods return a new string or a list, so you can build a clean pipeline without changing the original value. You will also normalize a messy list and unpack a guarded record.
Clean the edges
strip() removes whitespace from both ends. lower() and upper() change case. These methods return a new string; they do not modify the original. Chain them when you need both operations.
raw = " MAYA "
clean = raw.strip().lower()
print(clean)
print(raw)Chaining string methods
Split and join
split(separator) turns a string into a list of fields. join(iterable) turns a collection of strings into one string. The separator used by join is the string before the dot.
row = "latte,4.5,2"
fields = row.split(",")
print(fields)
print(" | ".join(fields))CSV-style text
Replace and slice
replace(old, new) swaps every matching substring. Slicing reads a range of characters: text[0:4] starts at index 0 and stops before index 4. Negative indexes count from the end.
text = "hello world"
print(text.replace("world", "Python"))
print(text[0:5])
print(text[-5:])Replacing and slicing
Normalize before comparing
User input often has extra spaces and inconsistent case. Normalize before comparing: strip each item, lowercase it, then join with a clear separator. If display needs the original capitalization, keep the display value and the normalized key separate.
raw = " Latte, Tea ,Mocha "
items = [part.strip().lower() for part in raw.split(",")]
print(items)
print(" | ".join(items))Clean each field, then join
Split, check, then unpack
split() turns a record into fields, and unpacking gives each field a name. Slicing extracts fixed parts such as a year or month. Check the field count before unpacking real data, because a missing field raises ValueError.
record = "2026-10-28|latte|4.50"
parts = record.split("|")
if len(parts) == 3:
date, name, price = parts
print(date[:4], date[5:7], date[8:10])
print(name.capitalize(), float(price))
else:
print("invalid record")A field-count guard before unpacking
Check the shape before converting
startswith(), endswith(), and removeprefix() check the structure of text before you convert it. Converting first and validating later mixes two failures: a malformed value and a ValueError. Check the currency symbol, strip it, then convert. When the shape is wrong, return a clear error instead of letting float() decide the message.
raw = "$4.50"
if raw.startswith("$"):
amount = float(raw.removeprefix("$"))
print(f"{amount:.2f}")
else:
print("missing currency symbol")Validate the prefix, then convert
Key points
- String methods return new values; the original string is unchanged.
- strip removes whitespace, while replace targets exact substrings.
- split turns text into fields; join turns fields back into text.
- A slice stops before the ending index.
- Normalize case and whitespace before comparing user input.
- Validate the shape of text before asking float() or int() to convert it.
Common mistakes
- Calling strip on a list instead of on each string item.
- Using join with a list of numbers instead of converting them to strings.
- Expecting text[1:3] to include index 3.
- Splitting first and forgetting to strip each field, leaving spaces inside the data.
- Calling float() on text that still contains a currency symbol.
Clean a raw name, split a comma-separated order, and join the fields with a dash.
Try it yourself
Change the values, predict the output, then run the code. The Python runtime is downloaded the first time you press Run, so the first run can take a few seconds.
Practice this lesson
12 questions with immediate explanations.