Real data is messy. Names arrive as ' aMArA ', phone numbers as '(555) 123-4567', prices as '$1,299.00'. Before you can analyse any of it, you have to clean it — and cleaning text is what string methods are for. This is the most-used skill in a data analyst's day.
What you'll learn
What
A string (str) is an ordered sequence of characters wrapped in quotes. String methods are built-in functions attached to every string that let you search, reshape, split, join, and reformat that text.
Why
Roughly 80% of real data-cleaning work is text wrangling. A model can't average the column 'Sales' if half the rows read '1,200' and the other half read '$1200 '. You standardise text first, then analyse.
Where it's used
Loading CSVs, parsing log files, cleaning survey responses, normalising customer names, extracting dates from filenames — every data pipeline touches strings before it touches numbers.
Where this runs in production
Search queries are lowercased and stripped so that ' STRANGER things ' matches the catalogue entry 'Stranger Things' regardless of how a user types it.
Hosts type cities inconsistently ('new york', 'New York ', 'NEW YORK'). A .strip().title() pipeline collapses them to one canonical 'New York' before grouping listings.
Bank descriptors arrive as raw strings. .split() and .replace() extract the merchant name and reference code so each charge can be matched to an order.
Picture the word 'SCORE' as five lockers in a row. The first locker is number 0, not 1 — Python counts from zero. So 'SCORE'[0] is 'S' and 'SCORE'[4] is 'E'. You can also count backwards: 'SCORE'[-1] is the last locker, 'E'.
text[start:stop] returns the characters from index start up to — but not including — stop. Leaving a side blank means 'all the way': text[:3] is the first three characters, text[3:] is everything from index 3 onward. A third number is the step: text[::2] takes every second character, text[::-1] reverses the whole string.
Calling name.upper() is like feeding a document into a photocopier set to 'ALL CAPS'. The original stays exactly as it was; you get a new copy back. If you don't keep the copy (clean = name.upper()), you've done the work for nothing.
raw = ' Amara Okafor ' clean = raw.strip() # removes leading/trailing spaces print(repr(clean)) # 'Amara Okafor' print(clean.upper()) # 'AMARA OKAFOR' print(clean.split()) # ['Amara', 'Okafor'] print(raw) # ' Amara Okafor ' (unchanged!)
Notice raw is untouched at the end — every method returned a new string. .strip() trims whitespace, .upper() recases, .split() breaks on spaces into a list. These three cover most day-one cleaning tasks.
name.strip() on its own line does nothing useful — the trimmed copy is thrown away. You must write name = name.strip() to keep it. This is the single most common string bug for beginners.
Click each stage to see how one messy customer name flows through common string methods into clean, analysis-ready data.
You want the first initial of a customer's name for a badge.
We store the string 'Priya'. Its characters sit at indexes 0 through 4: P(0) r(1) i(2) y(3) a(4).
Your task
A support system stores customer records as one raw string per line: 'lastname,firstname,city'. Clean and reformat the record below. Use the string methods provided — do not hard-code the final text.
Amara Okafor from Lagos
Write your solution in the editor on the right, then hit Run.
What does 'Sales'[1] return?
After running name = ' Bob ' and then name.strip(), what is the value of name?
What does 'temperature'[:4] return?
Which single expression standardises a value so all three variants match?
A sensor logs a reading as the string ' Temp: 21.5C '. Extract just the numeric part and print it as a float. Steps: strip the spaces, remove 'Temp: ' and the trailing 'C', then convert. Use reading = ' Temp: 21.5C '. Expected output: 21.5
Given a comma-separated tags string 'python, Data , SQL, data', print the number of UNIQUE tags after cleaning (lowercase everything and remove the stray spaces). One new helper: set() takes a list and throws away duplicates, so len(set(some_list)) counts unique items. Clean the whole string first with the methods you know, then split. Use tags = 'python, Data , SQL, data'. Expected output: 3
What does it mean that Python strings are immutable, and how do string methods work given that?
Immutable means a string's contents can never change after it's created — there's no way to overwrite a single character in place, and name[0] = 'X' raises a TypeError. String methods like .upper(), .strip(), and .replace() therefore don't modify the original; they construct and return a brand-new string, leaving the source untouched. In practice that means you must capture the result: name = name.strip(), not just name.strip(). Immutability is also why strings can be dictionary keys and why they're safe to share across your program without one part accidentally mutating another's copy.
Walk me through how you'd standardise a messy column of customer names for grouping.
I'd build a small chain that attacks each source of inconsistency. First .strip() to remove leading and trailing whitespace, which silently breaks grouping because 'Amara' and 'Amara ' look identical but aren't. Then a casing normaliser — .lower() or .title() depending on whether I want a canonical display form — so 'AMARA', 'amara', and 'Amara' collapse into one. If the field mixes several pieces, like 'last,first', I'd .split(',') and reassemble in a consistent order. In pandas the same logic vectorises with the .str accessor: df['name'].str.strip().str.title(). The principle is: normalise every axis of variation — whitespace, casing, ordering — before you group or join, or your counts will be silently wrong.
How does slicing work in Python, and why is the stop index exclusive?
Slicing uses text[start:stop:step]: it returns characters from index start up to but not including stop, optionally skipping by step. Omitting a bound means 'to the edge' — text[:3] is the first three characters, text[3:] is the rest, and negative indices count from the end so text[-1] is the last character and text[::-1] reverses the string. The stop being exclusive is deliberate: text[0:3] yields exactly 3 - 0 = 3 characters, so the length is trivial to reason about, and text[:n] + text[n:] always reconstructs the original with no overlap or gap. That half-open convention is consistent with range() and list slicing, so once you internalise it, it applies everywhere in Python.
Common Mistakes to Avoid
1) Expecting a method to change the string in place — name.strip() does nothing unless you write name = name.strip(), because strings are immutable. 2) Off-by-one indexing: the first character is [0], and a slice's stop index is excluded, so 'Sales'[0:2] is 'Sa', not 'Sal'. 3) Forgetting that .split() with no argument splits on any whitespace, while .split(',') splits only on commas — mixing them up mangles your fields. 4) Calling numeric conversion on dirty text: float('$1,299') raises a ValueError; strip the '$' and ',' first. 5) Comparing strings that differ only in case or spacing ('USA' vs 'usa ') and wondering why they don't match — normalise with .strip().lower() before comparing.
Ask the AI Tutor
Try these prompts in the AI Tutor panel: • 'ELI5: what does the slice [::-1] do and why?' • 'Quiz me on what .split() vs .join() return for a few examples.' • 'Show me a real data-cleaning bug caused by forgetting to reassign after .strip().' • 'Give me five messy price strings and let me practise converting each to a float.' • 'Interview mode: ask me why Python strings are immutable and grade my answer.'
Glossary
String (str) — an ordered, immutable sequence of characters in quotes. Index — the position number of a character, starting at 0; negatives count from the end. Slice — a substring pulled with [start:stop:step], where stop is excluded. Immutable — cannot be changed after creation; methods return a new string. Method — a function attached to an object, called with a dot: name.upper(). .strip() — removes surrounding whitespace. .lower()/.upper()/.title() — change casing. .replace(old, new) — swaps every occurrence of a substring. .split(sep) — breaks a string into a list. .join(list) — glues a list of strings into one. in — membership operator returning a bool. f-string — a formatted literal (prefixed f) embedding variables inside {}.
Recommended Resources
• Docs: the Python 'Text Sequence Type — str' reference lists every string method with examples. • Read: 'An Informal Introduction to Python → Strings' in the official tutorial for indexing and slicing from the source. • Practice: take five messy values from any spreadsheet you have and clean each one to a canonical form in a REPL. • Next in DSM: you can store and clean values — next you'll compute with them and build the boolean conditions behind every data filter in Operators & Expressions.
Recap
✓ A string is an ordered, immutable sequence of characters indexed from 0. ✓ Slice with [start:stop:step]; the stop index is excluded and negatives count from the end. ✓ Methods return a new string — always reassign (name = name.strip()). ✓ .strip(), .lower(), .upper(), and .title() are your core text-cleaning tools. ✓ .split() breaks text into a list; .join() glues a list back into text. ✓ Clean dirty numeric text with .replace() before calling float() or int(). Next up: Operators & Expressions. You can store and clean values — next you'll calculate with them, compare them, and combine comparisons into the boolean logic that powers every data filter.
Run your code to see the output here.