Track 3 · Lesson 1 of 5

Working with text in Python

Pull records apart and put them back together, in whole programs built from blanks and run in the page.


Most of what a script does is move text around: take a line apart, keep the field you want, put the fields back in a different order, print the result. Every program below is that job, six to eight lines long, with a few gaps to fill.

What you'll be able to do

  • Pick a slice out of a string and know what the numbers mean.
  • Take a record apart with split and read one field out of it.
  • Put fields back together with join, the right way round.
  • Loop over a list of lines and build a second list from them.

Step 1: Three slices out of one string

A slice is [start:stop], and it stops before the position you name. Three gaps, three slices, one printed line.

Three fields from one code Checkpoint
code = "INV-2026-0042"
kind =
year =
number =
print(kind, year, number)

Tap a piece to place it

Turn the switch off when you want to place the pieces yourself, and the mistakes become yours to find.

code[:3] is INV. code[4:8] starts at position four and stops before eight, which gives the year. code[-4:] counts four back from the end. One piece is wrong on purpose: code[3:] would run to the end of the string and swallow the rest.

Counting starts at zero, so position four is the fifth character. That is why the year starts at four and not at five: there is a dash at position three.

Step 2: A record is a row of fields

This is a real account line, seven fields separated by colons. Split it once, then read three of them.

Read a record Checkpoint
line = "root:x:0:0:root:/root:/bin/sh"
fields = line.(":")
name =
uid =
home = fields[5]
print(name, uid, home)

Tap a piece to place it

Turn the switch off when you want to place the pieces yourself, and the mistakes become yours to find.

Eight lines. fields is a list of seven strings, and the three reads pick out the name, the user id and the home directory. The password field sits at position one, which is why the id is at two and not at one.

This is the Python version of cut -d: -f1, with a difference worth remembering: in the shell you write a new pipeline for each field, while here you split once and index the list as often as you like.

Step 3: Join, and the way round it goes

join is the reverse of split, and it is written the way round that surprises everyone: the separator comes first.

Two ways to join Checkpoint
parts = ["one", "two", "three"]
dashed =
spaced =
print(dashed)
print(spaced)

Tap a piece to place it

Turn the switch off when you want to place the pieces yourself, and the mistakes become yours to find.

"-".join(parts) says: take this dash and use it to join this list. parts.join("-") is the natural guess and it fails, because a list has no such method. That is worth remembering, because it is the mistake almost everyone makes first.

The separator is a string, so " ".join(parts) uses a space and "".join(parts) glues the pieces with nothing between them.

Step 4: f-strings, and a method that returns something new

Gluing strings with + gets unreadable fast and breaks when one piece is a number. An f-string puts the values inside the text.

Build a line, then change it Checkpoint
name = "Termux"
version = 0.118
line =
upper =
print(line)
print(upper)

Tap a piece to place it

Turn the switch off when you want to place the pieces yourself, and the mistakes become yours to find.

The f before the quote is the whole trick: without it the braces are literal characters. And upper() with brackets returns a new string; line itself is untouched, which is why the first print still shows the original.

Step 5: Clean a field before you split it

Real data arrives with stray spaces. strip removes them from both ends.

Clean, then split Checkpoint
raw = " admin:user "
clean =
left, right =
print(left)
print(right)

Tap a piece to place it

Turn the switch off when you want to place the pieces yourself, and the mistakes become yours to find.

Six lines. raw.strip() gives admin:user, and then the split gives the two halves. left, right = ... unpacks a two-item list into two names in one go, which is the tidy way to do it.

raw.split(":") on the uncleaned value would give " admin" with the spaces still attached, and the print would show them. That is the quiet kind of bug that only shows up in the output.

Step 6: Loop over lines and build a list

The pattern that most scripts come down to: take a list of lines, keep one field from each, collect the results.

Collect one field from each line Checkpoint
lines = ["root:x:0", "daemon:x:1", "bin:x:2"]
names = []
for line in lines:
fields =
print(names)

Tap a piece to place it

Turn the switch off when you want to place the pieces yourself, and the mistakes become yours to find.

Eight lines, and this is the shape of a hundred real scripts. names = [] starts an empty list, the loop takes each line, splits it, and appends the first field. The print at the end shows the list with its brackets and quotes, which is how Python writes a list.

names.append(line) would keep the whole line instead of the name, and the output would show the colons.

Step 7: Type one yourself

Turn a dotted address into a dashed one, using split and join together.

Dots to dashes Checkpoint

Runs in your browser, and nothing is sent anywhere. Python starts loading in the background as you reach this cell, about six megabytes once. After that every cell on the site runs instantly until you close the tab.

Step 8: A mistake to find

The code runs and prints something, but it is wrong. Press Run and look at the output closely.

Find the mistake Find the mistake

Runs in your browser, and nothing is sent anywhere. Python starts loading in the background as you reach this cell, about six megabytes once. After that every cell on the site runs instantly until you close the tab.

It prints adminuser, with the colon gone, because the string inside the brackets is what goes between the pieces and that string is empty. Nothing raises, so the output is the only clue.

Quick reference

PieceWhat it does
code[:3]the first three characters
code[4:8]four characters starting at position four
code[-4:]the last four characters
line.split(":")a string into a list of fields
"-".join(parts)a list into a string, separator first
f"{name} {version}"values inside the text
raw.strip()remove spaces from both ends
left, right = ...unpack a two-item list into two names
names.append(x)add to the end of a list
line.upper()returns a new string, leaves the original alone

Next steps

Test yourself on this

4 questions and 1 task where you run a real command, with the reasoning explained either way.

Start