Python Strings, Slicing and Formatting
AI-assistedDrafted with AI assistance and reviewed before publishing; examples are version-pinned. Verify against official docs when in doubt.
Logs, configuration, API responses, and user input all arrive as text. Most of that text handling comes down to a dozen string operations and one formatting syntax.
Environment
Examples are verified on Python 3.13. Everything below runs in the REPL, so python is enough to follow along.
Creating strings
a = "double quotes"
b = 'single quotes'
c = """a
multi-line string"""
All three are equivalent. Pick one style and stay consistent; most codebases use double quotes.
Two prefixes matter in practice:
path = r"C:\Users\me\notes.txt" # raw: \n is not a newline
sql = """
SELECT id, name
FROM users
WHERE id = ?
"""
Indexing and slicing
Strings are immutable sequences: you can read characters by position, but not assign to them.
text = "Python"
text[0] # 'P'
text[-1] # 'n'
text[0:2] # 'Py' (start included, end excluded)
text[::-1] # 'nohtyP'
text[0] = "p" # TypeError: 'str' object does not support item assignment
text[::-1] reverses because the step is -1. The same slice syntax works on lists and tuples.
Methods you actually use
Every string method returns a new string; the original is untouched.
s = " Python,Go,Rust "
s.strip() # 'Python,Go,Rust'
s.split(",") # [' Python', 'Go', 'Rust ']
", ".join(["a", "b"]) # 'a, b'
s.replace("Go", "Java") # replaces all occurrences
s.lower() # 'python,go,rust'
Searching and testing:
"python" in s.lower() # True
s.strip().startswith("Py") # True
s.find("Go") # 8, or -1 when absent
s.count(",") # 2
find returns -1 when the substring is missing; index raises ValueError instead. Choose based on whether absence is normal or exceptional.
A standard cleanup pipeline:
raw = " Python , Go "
langs = [part.strip() for part in raw.split(",")]
# ['Python', 'Go']
f-strings
Since 3.6, f-strings are the default choice: readable, concise, and fast.
name = "Ada"
score = 92.5
print(f"{name} scored {score}")
# Ada scored 92.5
Anything after the colon is a format spec:
f"{score:.1f}" # '92.5' one decimal place
f"{score:>8.1f}" # ' 92.5' width 8, right aligned
f"{1234567:,}" # '1,234,567'
f"{0.873:.1%}" # '87.3%'
f"{name!r}" # "'Ada'" calls repr()
Expressions are allowed inside the braces, including calls and conditionals:
f"{len(name)} chars, {'long' if len(name) > 3 else 'short'}"
For quick debugging, = prints the expression next to its value:
print(f"{score=} {name=}")
# score=92.5 name='Ada'
Older styles still appear in existing code:
"%s scored %.1f" % (name, score)
"{} scored {:.1f}".format(name, score)
Both work; new code should use f-strings.
str versus bytes
str holds text, bytes holds raw bytes. Files and sockets deal in bytes, so the conversion is explicit:
text = "café"
data = text.encode("utf-8") # b'caf\xc3\xa9'
data.decode("utf-8") # 'café'
Always name the encoding when touching files or network payloads; relying on the platform default produces code that works on your machine and fails elsewhere.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("café")
Common mistakes
1. Building strings with + in a loop
result = ""
for part in parts:
result += part # allocates a new string every iteration
"".join(parts) is both shorter and faster.
2. Confusing split() with split(",")
"a b\tc".split() # ['a', 'b', 'c'] splits on any whitespace, drops empties
"a,,b".split(",") # ['a', '', 'b'] keeps empty fields
CSV-like data needs the explicit separator.
3. Mixing str and bytes
"abc" + b"def" # TypeError
Decide at the boundary: decode on input, encode on output.
4. Assuming a method mutates
s.upper() # discarded
s = s.upper() # what you meant
5. Formatting floats for money
f"{0.1 + 0.2:.2f}" hides the problem but does not fix the arithmetic. Use decimal.Decimal for currency.
Summary
- Strings are immutable; methods return new values.
- Slicing uses
start:stop:step, end excluded;[::-1]reverses. strip/split/joincover most text cleanup.- f-strings handle formatting; the spec follows the colon.
stris text,bytesis data on the wire: convert explicitly withencode/decode.
Next: lists and dictionaries, the two containers you will use most.