String Indexing and Slicing
Strings are sequences. Every character has a position (index) starting at 0. Negative indices count from the end.
s = "Python"
# P y t h o n
# 0 1 2 3 4 5 โ positive indices
# -6 -5 -4 -3 -2 -1 โ negative indices
print(s[0]) # 'P' โ first character
print(s[-1]) # 'n' โ last character
print(s[2]) # 't' โ third character
# Slicing: s[start:end:step] โ end is EXCLUSIVE
print(s[1:4]) # 'yth' โ indices 1, 2, 3
print(s[:3]) # 'Pyt' โ start to index 2
print(s[3:]) # 'hon' โ index 3 to end
print(s[::2]) # 'Pto' โ every 2nd character
print(s[::-1]) # 'nohtyP' โ reversed!
# Practical examples
url = "https://example.com/page"
domain = url[8:19] # 'example.com'
protocol = url[:5] # 'https'
# Check last N characters
filename = "document.pdf"
extension = filename[-3:] # 'pdf'Essential String Methods
Strings are immutable โ methods return new strings, they don't modify the original.
# Case methods
"hello".upper() # "HELLO"
"HELLO".lower() # "hello"
"hello world".title() # "Hello World"
"Hello World".swapcase() # "hELLO wORLD"
"hello".capitalize() # "Hello" (only first char)
# Whitespace
" hello ".strip() # "hello" (both sides)
" hello ".lstrip() # "hello " (left only)
" hello ".rstrip() # " hello" (right only)
# Search
"hello world".find("world") # 6 (index of first match, -1 if not found)
"hello world".index("world") # 6 (like find but raises ValueError if missing)
"hello world".count("l") # 3
"hello world".startswith("he") # True
"hello world".endswith("ld") # True
"world" in "hello world" # True
# Transform
"hello world".replace("world", "Python") # "hello Python"
"hello".center(11) # " hello "
"hello".ljust(10, "-") # "hello-----"
"hello".rjust(10, "-") # "-----hello"
"42".zfill(5) # "00042"
# Split and join
"one,two,three".split(",") # ['one', 'two', 'three']
"hello world".split() # ['hello', 'world'] (splits on whitespace)
"-".join(["one", "two", "three"]) # "one-two-three"
# Validation
"hello".isalpha() # True (all letters)
"123".isdigit() # True (all digits)
"abc123".isalnum() # True (letters or digits)
" ".isspace() # TrueString Formatting
f-Strings (Use These)
name = "Alice"
age = 30
score = 95.567
# Basic substitution
print(f"Name: {name}, Age: {age}")
# Expressions in f-strings
print(f"In 10 years: {age + 10}")
print(f"Upper: {name.upper()}")
# Format specifiers: {value:format}
print(f"Score: {score:.2f}") # 95.57 (2 decimal places)
print(f"Padded: {age:05d}") # 00030 (5 chars, zero-padded)
print(f"Width: {name:>10}") # " Alice" (right-align in 10 chars)
print(f"Width: {name:<10}") # "Alice " (left-align)
print(f"Width: {name:^10}") # " Alice " (center)
print(f"Thousands: {1000000:,}") # 1,000,000
# Debug format (Python 3.8+)
x = 42
print(f"{x = }") # x = 42 (prints name = value)
print(f"{x*2 = }") # x*2 = 84format() and % (Legacy โ Know Them)
# .format() method (Python 2.6+, still common)
"Hello, {}! You are {} years old.".format(name, age)
"Hello, {name}!".format(name="Alice")
"{0} and {1}".format("first", "second")
# % formatting (very old, avoid in new code)
"Hello, %s! Age: %d" % (name, age)
"Score: %.2f" % scoreSpecial String Types
# Raw strings โ backslashes are literal (great for file paths and regex)
normal = "C:\new_folder\test.txt" # \n = newline, \t = tab โ WRONG
raw = r"C:\new_folder\test.txt" # Literal backslashes โ CORRECT
# Byte strings โ sequences of bytes, not text
data = b"binary data"
print(type(data)) # <class 'bytes'>
data[0] # 98 (integer, not 'b')
# Encode/decode between str and bytes
text = "Hello"
encoded = text.encode("utf-8") # b'Hello'
decoded = encoded.decode("utf-8") # 'Hello'
# Multi-line strings
sql = """
SELECT *
FROM users
WHERE active = 1
ORDER BY name
"""Common String Patterns
# Check if string is a number
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
# Truncate long string with ellipsis
def truncate(text, max_len=50):
return text if len(text) <= max_len else text[:max_len-3] + "..."
# Extract domain from email
email = "alice@example.com"
domain = email.split("@")[1] # "example.com"
# Count words
text = "The quick brown fox"
word_count = len(text.split()) # 4
# Remove punctuation
import string
clean = text.translate(str.maketrans("", "", string.punctuation))
# Check palindrome
def is_palindrome(s):
s = s.lower().replace(" ", "")
return s == s[::-1]
is_palindrome("racecar") # True
is_palindrome("A man a plan a canal Panama") # True (after cleaning)Key Takeaways
- Slicing syntax:
s[start:end:step]โ end is exclusive, negatives from end - s[::-1] reverses any string (and any sequence)
- f-strings are the way: readable, fast, support expressions and format specs
- Strings are immutable: methods return new strings, originals unchanged
- Raw strings for paths:
r"C:\Users\file.txt"โ no escape processing
Practice Exercises
- Given
s = "Hello, World!", extract "World" using slicing โ without hardcoding the indices (usefind()to locate it first). - Write a function that checks if a string is a valid username: only letters and numbers, 3-15 characters.
- Reverse the words in a sentence. Input: "Hello World Python" โ Output: "Python World Hello". Do it in one line.
- Format a receipt: given a list of
(item, price)tuples, print a table where items are left-aligned and prices are right-aligned with 2 decimal places.