Skip to content

String Methods and Formatting

💡
Before you start

You need Python installed, and to know how to run a .py file. If python3 --version in a terminal prints a version number, you are ready. If it does not — or if you have never opened a terminal — do Getting Started with Python first; it installs Python and runs your first program, and takes about fifteen minutes. Nothing else is needed: no account, no payment, no extra software.

String Basics Recap

Strings are sequences of characters. You already know how to create them and use basic operations like concatenation. Now let's explore Python's powerful built-in string methods that save you from writing custom logic.

text = "Hello, World!"
print(type(text))       # <class 'str'>
print(len(text))        # 13
💡
Strings are immutable

String methods never modify the original string — they always return a new string. The original stays unchanged unless you reassign the variable.

Case Methods

text = "Hello, World!"

print(text.upper())        # HELLO, WORLD!
print(text.lower())        # hello, world!
print(text.title())        # Hello, World!
print(text.capitalize())   # Hello, world!
print(text.swapcase())     # hELLO, wORLD!

# Useful for case-insensitive comparison
user_input = "YES"
if user_input.lower() == "yes":
    print("Confirmed!")

Search and Check Methods

text = "Python is awesome and Python is fun"

# Find position of substring
print(text.find("awesome"))      # 10
print(text.find("missing"))      # -1 (not found)
print(text.index("awesome"))     # 10 (raises ValueError if not found)

# Count occurrences
print(text.count("Python"))      # 2
print(text.count("is"))          # 2

# Check start/end
filename = "report.pdf"
print(filename.startswith("report"))   # True
print(filename.endswith(".pdf"))       # True
print(filename.endswith((".pdf", ".doc")))  # True (tuple of suffixes)

Content Check Methods

print("hello123".isalnum())     # True  (letters + numbers only)
print("hello".isalpha())       # True  (letters only)
print("12345".isdigit())       # True  (digits only)
print("hello".islower())       # True  (all lowercase)
print("HELLO".isupper())       # True  (all uppercase)
print("   ".isspace())         # True  (whitespace only)

Modify and Clean Methods

# Strip whitespace (very common for user input)
dirty = "   hello world   "
print(dirty.strip())        # "hello world"
print(dirty.lstrip())       # "hello world   "
print(dirty.rstrip())       # "   hello world"

# Strip specific characters
url = "///path/to/page///"
print(url.strip("/"))       # "path/to/page"

# Replace substrings
text = "I like cats. Cats are great."
print(text.replace("cats", "dogs"))         # I like dogs. Cats are great.
print(text.replace("cats", "dogs", 1))      # Replace only first occurrence

Split and Join

These two methods are among the most useful in Python:

# Split a string into a list
sentence = "Python is a great language"
words = sentence.split()           # Split by whitespace (default)
print(words)                       # ['Python', 'is', 'a', 'great', 'language']

csv_data = "Alice,25,Engineer"
fields = csv_data.split(",")       # Split by comma
print(fields)                      # ['Alice', '25', 'Engineer']

# Limit splits
text = "one:two:three:four"
print(text.split(":", 2))          # ['one', 'two', 'three:four']

# Join a list into a string
words = ["Python", "is", "fun"]
print(" ".join(words))             # "Python is fun"
print("-".join(words))             # "Python-is-fun"
print(", ".join(words))            # "Python, is, fun"
💡
Split + Join pattern

A common pattern is to split a string, process the parts, and join them back. For example, to capitalize each word: " ".join(word.capitalize() for word in text.split())

String Slicing

text = "Python Programming"

# Syntax: string[start:end:step]
print(text[0:6])        # "Python"      (index 0 to 5)
print(text[7:])         # "Programming" (index 7 to end)
print(text[:6])         # "Python"      (start to index 5)
print(text[-11:])       # "Programming" (last 11 chars)
print(text[::2])        # "Pto rgamn"  (every 2nd char)
print(text[::-1])       # "gnimmargorP nohtyP" (reversed)

Advanced f-String Formatting

f-strings support powerful formatting beyond simple variable insertion:

# Number formatting
price = 49.99
print(f"Price: ${price:.2f}")           # Price: $49.99
print(f"Price: ${price:10.2f}")         # Price:      $49.99 (padded)

big = 1234567
print(f"Count: {big:,}")                # Count: 1,234,567

# Percentage
ratio = 0.856
print(f"Score: {ratio:.1%}")            # Score: 85.6%

# Padding and alignment
name = "Alice"
print(f"|{name:<10}|")    # |Alice     | (left-aligned)
print(f"|{name:>10}|")    # |     Alice| (right-aligned)
print(f"|{name:^10}|")    # |  Alice   | (centered)
print(f"|{name:*^10}|")   # |**Alice***| (centered with fill)

# Expressions inside f-strings
x = 10
print(f"{x} squared is {x**2}")         # 10 squared is 100
print(f"{'yes' if x > 5 else 'no'}")   # yes

Multi-line Strings

# Triple quotes for multi-line
message = """Dear User,

Thank you for signing up.
Your account is now active.

Best regards,
The Team"""

print(message)

# Raw strings (ignore escape characters)
path = r"C:\Users\name\documents"
print(path)     # C:\Users\name\documents (no escaping needed)

Practical Examples

# Clean and validate email
def clean_email(email):
    email = email.strip().lower()
    if "@" in email and "." in email.split("@")[1]:
        return email
    return None

print(clean_email("  Alice@Example.COM  "))  # alice@example.com
print(clean_email("invalid"))                 # None

# Parse a log line
log = "2026-03-04 10:30:15 ERROR Database connection failed"
parts = log.split(" ", 3)    # Split into max 4 parts
date, time, level, msg = parts
print(f"[{level}] {msg} at {date} {time}")
# [ERROR] Database connection failed at 2026-03-04 10:30:15

# Build a simple table
headers = ["Name", "Age", "City"]
rows = [
    ["Alice", "25", "London"],
    ["Bob", "30", "Paris"],
    ["Charlie", "28", "Berlin"]
]

for header in headers:
    print(f"{header:<10}", end="")
print()
print("-" * 30)
for row in rows:
    for cell in row:
        print(f"{cell:<10}", end="")
    print()

Now Do It Yourself: Five Steps

The methods above are the toolbox. This is the job: you will take one messy line of user input and turn it into a clean name, a username and an email address. Every result below is what Python actually printed when these lines were run.

1
Open Python and take a deliberately messy string

Go: open a terminal and type python3, then press Enter. You will see the >>> prompt.

Do: type this line, keeping the two spaces at each end exactly as shown.

raw = "  ALICE Johnson  "

You should see: nothing at all — assignment is silent. Type raw on its own and press Enter to check: it prints ' ALICE Johnson ', quotes and spaces included. That is real data as it arrives from a web form.

If not: if the spaces have vanished, your terminal or editor trimmed them on paste. Type the line by hand instead — the whole point of the next step is removing those spaces yourself.

2
Clean the edges and fix the shouting

Go: stay at the >>> prompt.

Do: run these two lines.

print(repr(raw.strip()))
print(raw.strip().title())

You should see: 'ALICE Johnson' then Alice Johnson. repr() is used on the first so you can see the quotes and confirm the spaces are gone; plain print would show a trimmed-looking string either way.

If not: if raw still has its spaces afterwards, that is correct and is the single most surprising thing about Python strings: they are immutable. raw.strip() does not change raw, it hands back a new string. Run name = "alice", then name.upper(), then name — it still prints alice. You must assign the result to keep it.

3
Break the name into its parts

Go: same prompt.

Do: run this one line.

print(raw.strip().title().split())

You should see: ['Alice', 'Johnson'] — a list of two strings. Called with no argument, split() breaks on any run of whitespace and quietly discards empty pieces, which is exactly what you want for human-typed input.

If not: if you get ['', '', 'Alice', 'Johnson', '', ''], you called split(" ") with an explicit space. That version treats every single space as a separator and keeps the empty gaps between them. Use bare split() for text a person typed.

4
Pull an email address apart by position

Go: same prompt.

Do: run these four lines.

e = "alice.johnson@example.com"
print(e[:e.index("@")])
print(e[e.index("@")+1:])
print(e[-3:])

You should see: alice.johnson, then example.com, then com. Slicing is [start:end], the end is not included, and a negative number counts back from the right — so [-3:] means "the last three characters".

If not: ValueError: substring not found means there is no @ in the string at all. index() raises rather than returning nothing; if the character might be absent, use e.find("@"), which returns -1 instead of raising.

5
Build the finished output

Go: leave the prompt with exit() and create a file called clean.py.

Do: put these five lines in it and run python3 clean.py.

parts = "  ALICE Johnson  ".strip().title().split()
first, last = parts[0], parts[1]
user = f"{first[0].lower()}{last.lower()}"
print(f"{first} {last} <{user}@example.com>")
print("-".join(["2026", "03", "04"]))

You should see: Alice Johnson <ajohnson@example.com> and then 2026-03-04. The f-string builds text from variables; join is split in reverse, and note it is called on the separator, not on the list.

If not: IndexError: list index out of range means the input had only one word, so parts[1] does not exist. Real input does that constantly — check len(parts) before unpacking. And if join raises TypeError: sequence item 0: expected str instance, int found, your list holds numbers: join only accepts strings.

🎉
Check yourself before moving on

Without scrolling up: after name = "alice" and name.upper(), what does name print, and why? If you can answer that, you have understood immutability — the idea behind almost every "but I changed it!" bug with Python strings. Answer: alice. Methods return a new string; the original is never modified. You need name = name.upper().

Now do it without the page: take the messy string " BOB smith " and produce bsmith@example.com. Same five moves, different input — if it works first time, the pattern has stuck.

Summary

  • Case: upper(), lower(), title(), capitalize()
  • Search: find(), count(), startswith(), endswith(), in
  • Clean: strip(), replace()
  • Split/Join: split() breaks strings apart, join() combines lists
  • Slicing: string[start:end:step] extracts substrings
  • f-strings: Support number formatting, alignment, padding, and expressions
🎉
String methods mastered!

You can now manipulate text like a pro. Next up: reading and writing files — making your programs work with data stored on disk.