Strings & f-strings

The Course
•
January 5, 2026
•
5 min read

Most of the data you will ever handle is text: names, addresses, log lines, JSON, HTML. Python’s string type is good enough that people pick the language for this reason alone.

Quotes

Single and double quotes do the same thing. Use whichever avoids escaping:

Three ways to quote Python
print('single')
print("double")
print("She said 'hello'")
print('It costs $5 - and that is "cheap"')

# Triple quotes span lines and keep the line breaks.
print("""Dear Ada,

Thank you for the algorithm.""")

f-strings

To put a value inside text, prefix the string with f and write the expression in braces. This is the modern way to format in Python, and the only one you need.

Formatting with f-strings Python
name = "Ada"
age = 36

print(f"{name} is {age} years old")

# Any expression fits inside the braces.
print(f"Next year {name} turns {age + 1}")

# :.2f rounds to 2 decimals, :, adds thousands separators.
price = 1234.5678
print(f"Price: {price:.2f}")
print(f"Big:   {1234567:,}")

# = is a debugging trick: it prints the expression and its value.
print(f"{age * 2 = }")
Format specifiers worth remembering

:.2f fixed decimals · :, thousands separators · :>10 right-align in 10 columns · :<10 left-align · :^10 centre · :.1% percentage.

Strings are sequences

A string is an ordered sequence of characters, and positions count from zero.

Indexing and slicing Python
word = "Python"

print(word[0])     # first character
print(word[5])     # sixth
print(word[-1])    # last - negative counts from the end
print(len(word))   # how many characters

# Slicing takes [start:stop] - stop is not included.
print(word[0:3])
print(word[:3])    # from the beginning
print(word[3:])    # to the end
print(word[::-1])  # every character, backwards

The half-open rule — start included, stop excluded — looks odd for about a day and then becomes convenient: word[:3] and word[3:] split cleanly with no overlap and no gap.

Useful methods

A method is a function that belongs to a value; you call it with a dot. Strings have dozens, and these are the ones that earn their keep:

String methods Python
raw = "  Ada Lovelace,Programmer  "

print(raw.strip())              # remove surrounding whitespace
print(raw.strip().upper())
print(raw.strip().lower())
print(raw.replace(",", " - "))
print(raw.strip().split(","))   # cut into a list on a separator

print("ada" in raw.lower())     # substring test
print(raw.strip().startswith("Ada"))
print("-".join(["2026", "01", "05"]))
Strings never change

Every method above returns a new string; none of them edits the original. raw.strip() on its own line does nothing useful — you have to keep the result: raw = raw.strip(). This is called immutability, and it is why strings are safe to share around a program.

Proof Python
name = "ada"
name.upper()          # result thrown away
print(name)

name = name.upper()   # result kept
print(name)

Escape sequences

Some characters need a backslash to write: \n is a newline, \t a tab, \" a literal quote, \\ a literal backslash.

Escapes Python
print("Line one\nLine two")
print("Name:\tAda")
print("A backslash: \\")

# A raw string turns escapes off - handy for Windows paths and regexes.
print(r"C:\new\table")

Before you write your own

Predict. Four lines. Decide each one before you press Run.

What will this print? Python
word = "spending"
print(word[0], word[-1])
print(word[:5])
print(f"{len(word)} letters")

answer = "  Yes "
print("yes" in answer.lower())
Check your prediction
s g
spend
8 letters
True

word[:5] stops before position 5, so it’s the first five characters: s p e n d. And answer.lower() is " yes ", which contains "yes" — the spaces don’t matter to in.

Fix. A survey answer should come out tidy as [blue] — the brackets are there so you can see any stray spaces. It comes out unchanged. Why?

Nothing happened Python
answer = "   BLue  "
answer.strip()
answer.lower()
print(f"[{answer}]")
Check your fix
answer = "   BLue  "
answer = answer.strip().lower()
print(f"[{answer}]")
[blue]

strip() and lower() each return a new string, and the original lines threw those new strings away. Keep the result by assigning it back — and you can chain the two methods, because strip() returns a string that has a lower() of its own.

Exercise

Clean up a messy record

The variable below holds a badly formatted record. Print it as:

ADA LOVELACE (programmer) - 36

You will need strip, split, upper, lower and an f-string.

record = "  ada lovelace | Programmer | 36  "

# Your code here
Hint 1: the idea

Separate, then tidy. split("|") cuts the record into three pieces, but each piece still has spaces around it. Strip each piece, change its case, and put the three back together with an f-string.

Hint 2: a first step

Start with parts = record.split("|") and print(parts). Look closely at what you get: the spaces are still there, which tells you what to do to each piece next. parts[0] is the name.

Show one solution
record = "  ada lovelace | Programmer | 36  "

parts = record.strip().split("|")
name = parts[0].strip().upper()
role = parts[1].strip().lower()
age = parts[2].strip()

print(f"{name} ({role}) - {age}")

Splitting first and stripping each piece afterwards is the usual shape for this kind of cleanup: separate, then tidy.

What you learned

  • Quotes are interchangeable; triple quotes span lines.
  • f-strings interpolate any expression, with format specifiers like :.2f.
  • Strings are zero-indexed sequences; slices are half-open, negatives count back.
  • Methods like strip, split, replace and join return new strings.
  • Strings are immutable — keep the result or nothing happened.
Last updated on January 5, 2026

Was this article helpful?

Your response is saved on this device.