Strings & String Formatting

Python Fundamentals
Course 1 ยท Chapter 5 ยท Strings & String Formatting

๐Ÿ”ค Strings & String Formatting

You've been using strings since Chapter 1 without a close look at what they can do. This chapter covers indexing and slicing, string immutability, the most common string methods, and Python's three ways to build formatted strings โ€” f-strings, .format(), and old-style % โ€” with a clear recommendation for which one to actually reach for.

โœ‚๏ธ String Indexing & Slicing

word = "Python"

print(word[0])       # P โ€” first character
print(word[-1])      # n โ€” last character, negative index
print(word[1:4])     # yth โ€” slice: start inclusive, stop exclusive
print(word[:3])      # Pyt โ€” omit start, defaults to 0
print(word[3:])      # hon โ€” omit stop, defaults to the end
print(word[::-1])    # nohtyP โ€” step of -1 reverses the string

Slice syntax is [start:stop:step] โ€” the same shape you'll see again on lists in Chapter 6. stop is exclusive, matching range() from the last chapter.

String Indexing: Go vs Kotlin vs Python

LanguageIndexing a string
GoA string is a byte slice โ€” indexing with s[0] gives a raw byte, not a character. Multi-byte UTF-8 characters (like emoji or accented letters) require iterating with range to get correct character boundaries.
Kotlins[0] gives a Char โ€” indexing is character-based like Python, inherited from Java's String behavior.
Pythons[0] gives a single-character string, always Unicode-aware โ€” no separate "byte vs character" distinction to worry about at this level.

๐Ÿ”’ Strings Are Immutable

A string can't be changed in place โ€” every string method that looks like it's "modifying" a string is actually returning a brand-new string:

name = "python"
upper_name = name.upper()

print(name)         # python โ€” unchanged
print(upper_name)   # PYTHON โ€” a new string

๐Ÿ› ๏ธ Common String Methods

s = "  Hello, World  "

s.strip()                  # "Hello, World" โ€” removes leading/trailing whitespace
s.lower()                  # "  hello, world  "
s.upper()                  # "  HELLO, WORLD  "
s.strip().split(", ")     # ['Hello', 'World']
"-".join(["a", "b", "c"])   # "a-b-c"
s.replace("World", "Python")  # "  Hello, Python  "
s.strip().startswith("Hello")  # True
s.strip().endswith("World")    # True
s.find("World")              # 9 โ€” index where it starts, or -1 if not found
๐Ÿ’ก join() Lives on the Separator, Not the List

"-".join(["a", "b", "c"]) reads backwards to most newcomers โ€” the separator string comes first, and the list of pieces to join is the argument. Building a string by repeatedly concatenating with + inside a loop works, but "".join(...) is the idiomatic and more efficient way to combine many pieces at once, since strings are immutable and each + creates yet another new string.

๐Ÿ“ f-strings: Formatted String Literals

An f-string embeds expressions directly inside a string, prefixed with f:

name = "Ada"
age = 28

print(f"{name} is {age} years old")
# Ada is 28 years old

print(f"Next year: {age + 1}")     # expressions work directly inside {}
# Next year: 29

pi = 3.14159265
print(f"Pi rounded: {pi:.2f}")   # format spec after the colon
# Pi rounded: 3.14

๐Ÿ“ .format() and % โ€” The Older Styles

# .format() โ€” pre-f-string standard, still common in older code
print("{} is {} years old".format(name, age))

# % formatting โ€” the oldest style, inherited from C's printf
print("%s is %d years old" % (name, age))

Which Style Should You Use?

f-strings (added in Python 3.6) are the modern, idiomatic choice โ€” they're more readable since the variable sits directly inside the string instead of matched up positionally, and they're generally faster. .format() and % both still appear constantly in real-world and older code, so recognizing them matters even though you should default to f-strings in new code you write.

Slicing

s[start:stop:step] โ€” stop is exclusive, negative indices count from the end.

Immutability

String methods never modify in place โ€” they always return a new string.

String Methods

.strip(), .split(), .join(), .replace(), .find() and more.

f-strings

f"{expr:.2f}" โ€” the modern, idiomatic way to build formatted strings.

๐Ÿ’ป Coding Challenges

Challenge 1: Reverse Words

Given the string "Python is fun", use .split() and .join() to print the words in reverse order: "fun is Python".

Goal: Practice combining .split() and .join() with slicing to reverse a sequence.

โ†’ Solution

Challenge 2: Formatted Receipt Line

Given item = "Coffee", price = 4.5, and qty = 3, use an f-string to print a line like "3x Coffee: $13.50", with the total formatted to exactly 2 decimal places.

Goal: Practice f-string expressions and the :.2f format spec together.

โ†’ Solution

Challenge 3: Palindrome Check

Write code that checks whether the string "racecar" is a palindrome (reads the same forwards and backwards), using slicing rather than a loop.

Goal: Practice using the [::-1] slice pattern to solve a real small problem.

โ†’ Solution

๐ŸŽฏ What's Next

Next chapter: Lists, Tuples & Sets โ€” mutable vs. immutable sequences, and a first look at comprehensions.