1.2.12 · D2Introduction to Programming (Python)

Visual walkthrough — String methods — upper, lower, strip, split, join, replace, find, format

2,024 words9 min readBack to topic

We only assume one thing you already met in Strings — indexing and slicing: a string is a row of characters with an address (an index) under each one, starting at 0. Everything else we earn here.


Step 1 — A string is an addressed row of characters

WHAT. Take the string s = "a,b,c". Write each character in its own box and put its index number underneath. The index is just "how many boxes from the left", starting at zero.

WHY. Every method we discuss is secretly a loop that walks these boxes left to right. If we cannot see the boxes and their addresses, split and join look like magic. They are not — they are bookkeeping.

PICTURE.

Figure — String methods — upper, lower, strip, split, join, replace, find, format

  • — the whole row (the original object we must never mutate).
  • — the single character sitting at address .
  • The two ',' characters at indices and are the separators — the "cut here" marks.

Step 2 — split walks the row and cuts at every separator

WHAT. s.split(",") slides across the boxes, remembering the start of the current piece. Every time it lands on a "," it saves everything since the last cut as one piece, then starts a fresh piece just after the comma.

WHY. Raw text arrives glued together ("id,name,city"). To work with the fields — index them, loop over them, validate them — we need them as separate items in a list. split is the tool that answers the question "where are the boundaries?" and hands back the pieces between them.

PICTURE. Follow the orange cut-lines; each blue block between two cuts becomes one list item.

Figure — String methods — upper, lower, strip, split, join, replace, find, format

  • The input "a,b,c" had 2 separators.
  • The output has 3 pieces. This is the heartbeat of the whole page: .

Step 3 — Empty pieces are real pieces (the degenerate cut)

WHAT. What if two separators sit next to each other, as in "a,,c"? There is nothing between them — but the counting law still holds, so the "nothing" becomes an empty string "" piece.

WHY. We must cover every input, including ugly ones. Beginners assume split "skips blanks". It does not, when you pass an explicit separator: the region between two adjacent cuts is genuinely empty, and an empty string is still a valid piece. Missing this is a top-3 real-world bug (a blank field silently vanishing or, worse, not vanishing).

PICTURE. The middle block has zero characters — draw it as a thin empty slot, still a block.

Figure — String methods — upper, lower, strip, split, join, replace, find, format

  • separators pieces, exactly as the law demands.
  • The empty string "" has length but still occupies a slot in the list.

Step 4 — join is the reverse walk: write a separator between, never after

WHAT. "-".join(["a","b","c"]) walks the list and writes each piece. Before every piece except the first, it first writes the separator. So the separator lands strictly between consecutive pieces.

WHY. We need the inverse of split: take the basket of pieces and rebuild one row. The only design decision is where the separator goes. Putting it between (not after every piece) is what makes join the true opposite of split — otherwise we'd get a trailing "a-b-c-".

PICTURE. Watch the if i > 0 gate: it blocks the separator only on the very first piece.

Figure — String methods — upper, lower, strip, split, join, replace, find, format
def my_join(sep, parts):
    out = ""
    for i, p in enumerate(parts):
        if i > 0:          # gate: no separator BEFORE the first piece
            out += sep      # separator goes BETWEEN pieces
        out += p            # then the piece itself
    return out

  • For pieces, the gate fires on — that is exactly separators.
  • This mirrors Step 2's law from the other side: .

Step 5 — The round-trip: split then join gives back the original

WHAT. Put Steps 2 and 4 together with the same separator. Split cut the row into pieces; join now welds those pieces back with the same comma into the exact same row.

WHY. This is the parent note's central result. It is the reason you can confidently disassemble text, transform the pieces, and reassemble without corrupting structure — the backbone of every CSV parser, path builder, and log formatter.

PICTURE. Top row splits into blocks; bottom row welds them back — the two rows are identical strings.

Figure — String methods — upper, lower, strip, split, join, replace, find, format

Step 6 — The edge case where the round-trip still works: empty pieces survive

WHAT. Does the identity survive the ugly "a,,c" from Step 3? Yes — because join faithfully re-inserts a separator around the empty piece too.

WHY. A "law" that only works on pretty inputs is not a law. We must check the degenerate case explicitly. Since split kept the empty piece, join writes a separator both before and after it, restoring the ,, double-comma exactly.

PICTURE. The empty slot survives the round-trip; the double-comma reappears untouched.

Figure — String methods — upper, lower, strip, split, join, replace, find, format

  • Three pieces two separators re-inserted the original two commas return.
  • The empty string contributes nothing visible but still holds its place between the two commas.

Step 7 — Where the round-trip BREAKS: bare split() vs split(sep)

WHAT. Now use the whitespace-collapsing bare split() on " a b ". It drops leading/trailing blanks and collapses runs. Weld it back with a single space and you do not recover the original.

WHY. The identity in Step 5 has a hidden condition: the same separator, kept faithfully. Bare split() is a different, lossy tool — it throws information away on purpose (great for cleaning human text, fatal for reversibility). Showing exactly why it breaks protects you from silent data loss.

PICTURE. Extra spaces are discarded (red), so the rebuilt row is shorter than the original.

Figure — String methods — upper, lower, strip, split, join, replace, find, format

  • The lost leading/trailing spaces and the collapsed run are gone forever — no separator count can bring them back.
  • Rule: the round-trip identity holds only for split(sep) with an explicit sep, never for bare split().
Recall Which of these round-trips is safe?

"a,,c" with split(",") then ",".join(...) ::: Safe — empty pieces are kept, so it rebuilds exactly. " a b " with bare split() then " ".join(...) ::: NOT safe — whitespace is collapsed and trimmed away, losing information.


The one-picture summary

Figure — String methods — upper, lower, strip, split, join, replace, find, format

One string flows down through split(sep) into a basket of k+1 pieces (empties included), then flows back up through sep.join(...) re-inserting exactly k separators — landing on a new object equal to the original. The only leak in the pipe is bare split(), which secretly deletes whitespace and makes the trip one-way.

Recall Feynman retelling — explain the whole walkthrough to a 12-year-old

Picture a train of letter-cars, with a number painted under each car (Step 1). A comma is a special "coupling you can unhook" (Step 2). split walks the train and unhooks at every comma, leaving a row of little trains in a basket. If two commas were touching, the little train between them has zero cars — but it's still a train, an empty one, and it stays in the basket (Step 3). To rebuild, join lines the little trains up and drops one coupling between each pair — never before the first and never after the last, so you always use one fewer coupling than you have trains (Step 4). Do both with the same comma-coupling and you rebuild the exact same train — a fresh copy, because the original could never be touched (Steps 5–6). The one trap: if instead of a real coupling you used the "gobble all the empty space" rule (bare split()), it quietly throws away the blank gaps, and no amount of gluing brings them back (Step 7).


Connections

  • Strings — indexing and slicing — the addressed boxes of Step 1 come from here.
  • Listssplit produces one, join consumes one.
  • Immutability in Python — why the round-trip returns a new equal object, not the same one.
  • f-strings — the modern way to reassemble text without join for simple cases.
  • Boolean truthiness — why an empty piece "" is falsy yet still a real list item.
  • User input and validation — split→clean→join is the daily workflow.
  • Parent: Hinglish version →