Skip to main content
Python · lesson 6 of 34
Python beginner Lesson 6 of 34

Python Strings

Slice, search, split, join and format Python strings with f-strings and format specs, plus escapes and raw strings, each example with real output.

By SkillByExample · Updated

Output below is from Python 3.13.

String Basics

Strings in Python are immutable sequences of Unicode characters (code points). Once created, you can’t change individual characters — strings are “value types” that are copied by reference but never mutated in place. Every string operation returns a new string object.

# strings.py
name = "Alice"
greeting = "Hello, " + name + "!"
print(greeting)

# String methods return new strings — original is unchanged
shouted = greeting.upper()
print(shouted)
print(greeting)  # still lowercase
$ python strings.py
Hello, Alice!
HELLO, ALICE!
Hello, Alice!

Slicing and Indexing

Strings support the same indexing and slicing syntax as lists — the first character is at index 0, the last at -1.

# slicing.py
text = "Python Programming"

print(text[0])       # P (first character)
print(text[-1])      # g (last character)
print(text[0:6])     # Python
print(text[7:])      # Programming
print(text[:6])      # Python
print(text[::2])     # every other character
print(text[::-1])    # reversed: gnimmargorP nohtyP
$ python slicing.py
P
g
Python
Programming
Python
Pto rgamn
gnimmargorP nohtyP

Slices stop before the end index, so text[0:6] is six characters. text[::2] takes every second character from index 0 — the space at index 6 counts as one of them, which is why the result is Pto rgamn and not every other letter. A step of -1 walks backwards, reversing the string.

F-Strings (Formatted String Literals)

F-strings (introduced in Python 3.6) are the modern way to embed values into strings. Prefix the string with f and wrap expressions in {} — they’re evaluated at runtime and inserted into the string.

# fstrings.py
name = "Bob"
age = 25
price = 19.99

print(f"Hello, {name}!")
print(f"You are {age} years old.")
print(f"Price: ${price}")
print(f"Price with tax: ${price * 1.08:.2f}")
print(f"Result of 2+2 = {2+2}")
$ python fstrings.py
Hello, Bob!
You are 25 years old.
Price: $19.99
Price with tax: $21.59
Result of 2+2 = 4

The :.2f after an expression is a format specifier — it controls how the value is rendered (in this case, 2 decimal places).

Common String Methods

Here are the most-used string methods. None of them modify the original string — they all return a new string.

# methods.py
sentence = "  Hello, World!  "

print(sentence.strip())           # "Hello, World!" — removes leading/trailing whitespace
print(sentence.lower())           # "  hello, world!  "
print(sentence.upper())           # "  HELLO, WORLD!  "
print(sentence.title())           # "  Hello, World!  "
print(sentence.replace("World", "Python"))  # "  Hello, Python!  "
print(sentence.split(","))        # ['  Hello', ' World!  ']
print(sentence.split())           # ['Hello,', 'World!']  — splits on any whitespace
print("-".join(["a", "b", "c"]))  # "a-b-c"
print(sentence.find("World"))     # 9 — index of first occurrence, or -1 if not found
print(sentence.count("o"))        # 2 — counts occurrences
print(sentence.startswith("  Hello"))  # True
$ python methods.py
Hello, World!
  hello, world!  
  HELLO, WORLD!  
  Hello, World!  
  Hello, Python!  
['  Hello', ' World!  ']
['Hello,', 'World!']
a-b-c
9
2
True

Escape Sequences and Raw Strings

Some characters can’t appear directly in a string — you need escape sequences. A raw string (r"...") treats backslashes as literal characters, which is essential for Windows paths and regex patterns.

# escaping.py
newline = "Line 1\nLine 2"
tabbed = "Col1\tCol2"
backslash = "C:\\Users\\alice"   # need to escape backslashes
raw_path = r"C:\Users\alice"     # raw string — backslashes are literal

print(newline)
print(tabbed)
print(backslash)
print(raw_path)
$ python escaping.py
Line 1
Line 2
Col1	Col2
C:\Users\alice
C:\Users\alice

Multiline Strings

Triple-quoted strings ("""...""" or '''...''') span multiple lines and preserve formatting. They’re commonly used for docstrings, SQL queries, and template text.

# multiline.py
html = """<div class="container">
    <h1>Welcome!</h1>
    <p>Hello, World!</p>
</div>"""

print(html)
$ python multiline.py
<div class="container">
    <h1>Welcome!</h1>
    <p>Hello, World!</p>
</div>

String Formatting Methods

# formatting.py
name = "Alice"
items = 5
price = 12.50

# 1. F-strings (modern, recommended)
msg1 = f"{name} bought {items} items for ${price:.2f}"
print(msg1)

# 2. .format() (older but flexible)
msg2 = "{} bought {} items for ${:.2f}".format(name, items, price)
print(msg2)

# 3. % formatting (legacy)
msg3 = "%s bought %d items for $%.2f" % (name, items, price)
print(msg3)

# Alignment in format specs
print(f"|{name:<10}|{items:>5}|{price:>10.2f}|")
$ python formatting.py
Alice bought 5 items for $12.50
Alice bought 5 items for $12.50
Alice bought 5 items for $12.50
|Alice     |    5|     12.50|

All three styles produced the same sentence. In the last line, <10 left-aligns in a 10-character field, >5 right-aligns, and >10.2f rounds to two decimals and right-aligns the whole result — 12.50 plus five spaces of padding — in 10 characters.

Checking Membership and Patterns

# membership.py
text = "The quick brown fox"

print("quick" in text)          # True — substring check
print("Quick" in text)          # False — case-sensitive
print("xyz" in text)            # False

# Check if a string contains only certain characters
print("12345".isdigit())        # True
print("hello".isalpha())        # True
print("abc123".isalnum())       # True — alphanumeric
print("  hello  ".istitle())    # False
$ python membership.py
True
False
False
True
True
True
False

Practice

1. Reverse a string: Write code that reverses a string using slicing.

Solution
text = "Hello, World!"
reversed_text = text[::-1]
print(reversed_text)
$ python reverse.py
!dlroW ,olleH

The slice [::-1] means “start at the end, end at position 0, step backwards by 1.”

2. Check for anagrams: Two strings are anagrams if they contain the same letters in a different order. Write a function that checks this.

Solution
def is_anagram(s1, s2):
    # Remove spaces and lowercase for case-insensitive comparison
    clean_s1 = s1.replace(" ", "").lower()
    clean_s2 = s2.replace(" ", "").lower()
    return sorted(clean_s1) == sorted(clean_s2)

print(is_anagram("Listen", "Silent"))    # True
print(is_anagram("Hello", "World"))      # False
$ python anagram.py
True
False

By sorting the characters of both strings, we can compare them directly — if the sorted versions match, the original strings are anagrams.

3. Extract domain from email: Given an email address, extract the domain (everything after the @).

Solution
email = "alice@example.com"
domain = email.split("@")[1]
print(domain)
$ python email.py
example.com

split("@") breaks the string into ["alice", "example.com"], and [1] selects the second element.

Frequently Asked Questions

Should I use .format(), f-strings, or % formatting?
Use f-strings (Python 3.6+) — they're the most readable and performant. Avoid % formatting in new code. .format() is fine for compatibility with older Python versions.
How do I include special characters in strings?
Use escape sequences like \n (newline), \t (tab), or \' (single quote). For Windows paths, prefer raw strings (r'...') or forward slashes.
Are strings mutable in Python?
No — strings are immutable. Every method that appears to modify a string actually returns a new string object, and assigning to an index such as s[0] = 'x' raises TypeError. To build a string from many pieces, collect them in a list and call ''.join().
What is the difference between str.split() and str.split(' ')?
split() with no argument splits on any run of whitespace and drops empty strings, so leading, trailing and repeated spaces disappear. split(' ') splits on every single space and keeps the empty strings between consecutive spaces.
How do I format a number with two decimal places or thousands separators?
Use a format spec inside an f-string: f'{price:.2f}' gives two decimals, f'{n:,}' adds comma thousands separators, and f'{ratio:.1%}' shows a percentage. The same specs work with format() and str.format().