Section · 01
Three ways to write a string
Strings hold text. Three legal ways to write them:
single = 'York'
double = "York"
triple = """York
spans
multiple lines"""Single and double quotes do the same thing. Pick double quotes by default; switch to single quotes when your string contains a double quote (or vice versa) so you don’t have to escape:
message = "Don't quote me on that." # easy
message = 'Don\'t quote me on that.' # works but ugly
message = 'She said "hello".' # easy
message = "She said \"hello\"." # works but uglyTriple-quoted strings are for multi-line text — usually for docstrings (the documentation at the top of a function) or templated chunks of HTML/SQL/JSON.
Escape sequences
A backslash starts an “escape sequence” inside a string. Three you’ll see constantly:
"line one\nline two" # \n is a newline
"col1\tcol2" # \t is a tab
"path: C:\\Users\\York" # \\ is a literal backslashIf you have a string with lots of backslashes (Windows paths, regular expressions), prefix with rfor “raw string” and Python will leave the backslashes alone:
path = r"C:\Users\York\Documents" # no escaping neededSection · 02
Combining and formatting
You can glue strings together with +:
first = "Ada"
last = "Lovelace"
full = first + " " + last # "Ada Lovelace"This works but reads badly the moment you need to insert numbers or more than two pieces. The modern Python answer is the f-string — prefix a string with f and put expressions in curly braces:
name = "Ada"
balance = 1287.45
print(f"Hi {name}, your balance is ${balance:.2f}.")
# "Hi Ada, your balance is $1287.45."The format spec after the colon controls how the value is displayed:
f"{1287.5:.2f}" # "1287.50" — 2 decimal places
f"{1287:,}" # "1,287" — thousands separator
f"{42:>6}" # " 42" — right-align in 6 chars
f"{42:0>4}" # "0042" — pad with zeros
f"{0.873:.1%}" # "87.3%" — percentThe older way (.format() and % formatting) still works but you should default to f-strings. They read top-to-bottom, they handle expressions, and they’re faster.
Section · 03
Indexing and slicing — same as lists
A string is technically a sequence of characters, which means you can index into it like a list. Indexes start at zero:
name = "Lovelace"
name[0] # "L"
name[1] # "o"
name[-1] # "e" — last
name[0:4] # "Love"
name[-4:] # "lace"
len(name) # 8One important thing: strings are immutable. You cannot change a character in place:
name = "lovelace"
name[0] = "L" # TypeError — 'str' object does not support item assignment
# Build a new string instead:
name = "L" + name[1:] # "Lovelace"Immutability sounds annoying but it’s the reason strings can be used as dictionary keys, can be safely passed between functions without surprises, and are blazingly fast for comparison.
Section · 04
The 8 methods you'll actually use
Strings have ~40 methods. You’ll use the same eight 95% of the time. Memorize these:
text = " Hello, World! "
text.strip() # "Hello, World!" — trims whitespace from both ends
text.lower() # " hello, world! "
text.upper() # " HELLO, WORLD! "
text.replace("World", "York") # " Hello, York! "
"Hello, World!".split(",") # ["Hello", " World!"]
",".join(["a", "b", "c"]) # "a,b,c"
"hello.txt".startswith("hello") # True
"hello.txt".endswith(".txt") # TrueWorth knowing: every method returns a new string. The original is unchanged (because strings are immutable). This trips people up:
# WRONG — .strip() returns a new string; the original is unchanged
name = " ada "
name.strip()
print(name) # " ada " — still has spaces!
# RIGHT — capture the return value
name = name.strip()
print(name) # "ada"Real-world example: clean a user signup
raw_email = input("Email: ").strip().lower()
if not raw_email.endswith("@yorksims.com"):
print("Sorry — yorksims.com emails only.")
elif "+" in raw_email:
print("No plus-aliases please.")
else:
username = raw_email.split("@")[0]
print(f"Welcome, {username}.")Six lines, four string methods, no regular expressions. That covers a huge percentage of real text-handling work. Reach for fancier tools (regex, parsers) only when these stop being enough.