Strings: The Complete Guide
Strings: The Complete Guide
Strings are everywhere in Python — user input, file contents, API responses, web pages. Mastering them is not optional. This lesson covers every string technique you'll actually use, from basic creation to advanced formatting.
Creating Strings
Python gives you three ways to create strings, each with a purpose:
# Single and double quotes — interchangeable
name = 'Alice'
greeting = "Hello, World!"
# Use the other quote type to avoid escaping
message = "It's a great day" # single quote inside double quotes
html = 'He said "Python rocks"' # double quotes inside single quotes
# Triple quotes — for multiline text
bio = """My name is Alice.
I love Python.
I write code every day."""
print(bio)
# My name is Alice.
# I love Python.
# I write code every day.
String Indexing and Slicing
Strings are sequences. Every character has a position (index) starting at 0. Python also supports negative indexing from the end:
word = "Python"
# P y t h o n
# index: 0 1 2 3 4 5
# neg: -6-5-4-3-2-1
print(word[0]) # P
print(word[1]) # y
print(word[-1]) # n (last character)
print(word[-2]) # o (second to last)
Slicing extracts a portion of the string using [start:stop:step]:
text = "Hello, Python!"
print(text[0:5]) # Hello (index 0 up to but not including 5)
print(text[7:]) # Python! (from index 7 to end)
print(text[:5]) # Hello (from start to index 5)
print(text[-7:]) # Python! (last 7 characters)
print(text[::2]) # Hlo yhn (every other character)
print(text[::-1]) # !nohtyP ,olleH (reversed!)
Slicing never raises an IndexError — if the indices are out of range, Python just returns what's available.
String Immutability
This is crucial: strings cannot be changed after creation. They are immutable.
word = "hello"
# This raises a TypeError
# word[0] = "H" # TypeError: 'str' object does not support item assignment
# Instead, create a new string
word = "H" + word[1:]
print(word) # Hello
Every string method returns a new string. The original is never modified.
Essential String Methods
Python's string methods are all you need for 95% of text processing tasks.
Case Methods
text = " Hello, Python! "
print(text.upper()) # " HELLO, PYTHON! "
print(text.lower()) # " hello, python! "
print(text.title()) # " Hello, Python! "
print(text.capitalize()) # " hello, python! " (only first char of whole string)
print(text.swapcase()) # " hELLO, pYTHON! "
Stripping Whitespace
text = " hello world "
print(text.strip()) # "hello world" — removes both ends
print(text.lstrip()) # "hello world " — removes left only
print(text.rstrip()) # " hello world" — removes right only
# Strip specific characters
filename = "###report.csv###"
print(filename.strip("#")) # "report.csv"
Splitting and Joining
split() and join() are workhorses for parsing and building text:
# split() — break string into a list
sentence = "the quick brown fox"
words = sentence.split() # splits on whitespace by default
print(words) # ['the', 'quick', 'brown', 'fox']
csv_line = "Alice,30,Engineer"
parts = csv_line.split(",")
print(parts) # ['Alice', '30', 'Engineer']
# split with maxsplit
data = "one:two:three:four"
print(data.split(":", 2)) # ['one', 'two', 'three:four']
# join() — combine a list into a string
words = ['Python', 'is', 'great']
sentence = " ".join(words)
print(sentence) # Python is great
# Join with different separators
print(", ".join(["apple", "banana", "cherry"])) # apple, banana, cherry
print("-".join("ABC")) # A-B-C
Searching Within Strings
text = "The quick brown fox jumps over the lazy dog"
# find() — returns index, or -1 if not found
print(text.find("fox")) # 16
print(text.find("cat")) # -1
# index() — like find(), but raises ValueError if not found
print(text.index("fox")) # 16
# count() — how many times does a substring appear?
print(text.count("the")) # 1 (case-sensitive)
print(text.lower().count("the")) # 2
# startswith() and endswith()
url = "https://python.org"
print(url.startswith("https")) # True
print(url.endswith(".org")) # True
print(url.startswith(("http", "ftp"))) # True — accepts a tuple!
Replacing Text
sentence = "I love Java. Java is great."
new_sentence = sentence.replace("Java", "Python")
print(new_sentence) # I love Python. Python is great.
# Replace only the first occurrence
partial = sentence.replace("Java", "Python", 1)
print(partial) # I love Python. Java is great.
Checking String Content
print("hello".isalpha()) # True — all letters
print("hello123".isalpha()) # False — contains digits
print("123".isdigit()) # True — all digits
print("abc123".isalnum()) # True — letters or digits
print(" ".isspace()) # True — all whitespace
print("Hello World".istitle()) # True — title case
The in Operator — Substring Membership
text = "Python is amazing"
print("Python" in text) # True
print("python" in text) # False — case-sensitive
print("python" in text.lower()) # True
print("Java" not in text) # True
# Extremely useful in conditionals
email = "user@example.com"
if "@" in email and "." in email:
print("Looks like a valid email") # Looks like a valid email
f-Strings: The Full Power
f-strings (available since Python 3.6) are the modern standard for string formatting:
name = "Alice"
age = 30
score = 95.678
# Basic variable embedding
print(f"Name: {name}, Age: {age}") # Name: Alice, Age: 30
# Expressions — any valid Python expression works inside braces
print(f"In 5 years: {age + 5}") # In 5 years: 35
print(f"Upper: {name.upper()}") # Upper: ALICE
print(f"Initials: {name[0]}.") # Initials: A.
# Number formatting
print(f"Score: {score:.1f}") # Score: 95.7 (1 decimal)
print(f"Score: {score:.2f}") # Score: 95.68 (2 decimals)
print(f"Big: {1234567:,}") # Big: 1,234,567 (comma separator)
print(f"Percent: {0.875:.1%}") # Percent: 87.5%
print(f"Hex: {255:#x}") # Hex: 0xff
# Width and alignment
print(f"{'Left':<10}|{'Center':^10}|{'Right':>10}")
# Left | Center | Right
# Debugging with = (Python 3.8+)
x = 42
print(f"{x = }") # x = 42 — shows name AND value
Raw Strings
Prefix with r to treat backslashes as literal characters. Essential for file paths and regex:
# Without raw string — \n is a newline, \t is a tab
path = "C:\new_folder\table.csv"
print(path)
# C:
# ew_folder able.csv — oops!
# With raw string — backslashes are literal
path = r"C:\new_folder\table.csv"
print(path) # C:\new_folder\table.csv
# Also useful for regex patterns
import re
pattern = r"\d+\.\d+" # matches decimal numbers like 3.14
matches = re.findall(pattern, "pi is 3.14 and e is 2.71")
print(matches) # ['3.14', '2.71']
String Comparison
Strings compare lexicographically (character by character using Unicode values):
print("apple" == "apple") # True
print("apple" == "Apple") # False — case-sensitive
print("apple" < "banana") # True — 'a' comes before 'b'
print("b" > "a") # True
print("Z" < "a") # True — uppercase letters come before lowercase in Unicode
# Case-insensitive comparison
s1 = "Hello"
s2 = "hello"
print(s1.lower() == s2.lower()) # True
Multiline Strings in Practice
# HTML template
html_template = """
<!DOCTYPE html>
<html>
<head><title>{title}</title></head>
<body><h1>{heading}</h1></body>
</html>
""".strip()
# SQL query stored cleanly
query = """
SELECT name, email
FROM users
WHERE active = 1
ORDER BY name
""".strip()
print(query)
# SELECT name, email
# FROM users
# WHERE active = 1
# ORDER BY name
Practical Exercises
Exercise 1: Username normalizer
def normalize_username(raw_input):
"""Clean and normalize a username."""
cleaned = raw_input.strip() # remove leading/trailing spaces
cleaned = cleaned.lower() # lowercase
cleaned = cleaned.replace(" ", "_") # replace spaces with underscores
return cleaned
print(normalize_username(" Alice Smith ")) # alice_smith
print(normalize_username("BOB JONES")) # bob_jones
Exercise 2: Simple CSV parser
def parse_csv_line(line):
"""Parse a CSV line into a dictionary."""
fields = line.strip().split(",")
return {
"name": fields[0],
"age": int(fields[1]),
"city": fields[2]
}
record = parse_csv_line("Alice,30,New York")
print(record) # {'name': 'Alice', 'age': 30, 'city': 'New York'}
print(f"{record['name']} is {record['age']} years old, lives in {record['city']}.")
# Alice is 30 years old, lives in New York.
Exercise 3: Password validator
def validate_password(password):
errors = []
if len(password) < 8:
errors.append("at least 8 characters required")
if not any(c.isupper() for c in password):
errors.append("must contain an uppercase letter")
if not any(c.isdigit() for c in password):
errors.append("must contain a digit")
return errors
issues = validate_password("hello")
if issues:
print("Password issues: " + ", ".join(issues))
# Password issues: at least 8 characters required, must contain an uppercase letter, must contain a digit
issues = validate_password("SecurePass1")
print(issues) # [] — no issues!
What's Next
You now have a complete toolkit for working with text in Python. In the next lesson, we tackle control flow — teaching Python to make decisions using if, elif, and else, including Python 3.10's powerful new match/case statement.
Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises