String Formatting with f-Strings

f-Strings are Python's modern approach to string formatting, introduced in Python 3.6. This post covers the syntax, embedded expressions, format specifiers for alignment and decimal places, and the Python 3.8 debugging shortcut. Practical examples show why f-Strings are cleaner and less error-prone

String Formatting with f-Strings

If you've been writing Python for a while, you've probably built strings by joining pieces together with the + operator. It works, but it gets messy fast. f-Strings are Python's modern answer to this problem, and once you start using them, you won't look back.

What Is an f-String?

An f-String (short for formatted string literal) is a string that starts with the letter f before the opening quote. Inside the string, you can embed Python expressions directly using curly braces {}. Python evaluates those expressions and drops the result straight into the string.

Here's the simplest possible example:

name = "Alice"
greeting = f"Hello, {name}!"
print(greeting)
# Output: Hello, Alice!

No concatenation, no type conversion headaches. Just clean, readable code.

Why Not Just Use Concatenation?

Before f-Strings (introduced in Python 3.6), developers used string concatenation or the older .format() method. Compare these three approaches doing the same thing:

username = "Bob"
score = 95

# Old way: concatenation
print("User: " + username + " scored " + str(score) + " points.")

# Older modern way: .format()
print("User: {} scored {} points.".format(username, score))

# f-String way
print(f"User: {username} scored {score} points.")

Notice that with concatenation you also need str(score) to convert the integer to a string. f-Strings handle that conversion automatically, which removes an entire category of common bugs.

Embedding Expressions

The curly braces in an f-String don't just accept variable names. You can put any valid Python expression inside them:

a = 10
b = 3

print(f"Sum: {a + b}")
print(f"Product: {a * b}")
print(f"Is a greater than b? {a > b}")

# Output:
# Sum: 13
# Product: 30
# Is a greater than b? True

You can even call functions or methods directly inside the braces:

city = "london"
print(f"Welcome to {city.title()}!")
# Output: Welcome to London!

Format Specifiers

f-Strings support format specifiers using a colon : inside the curly braces. This is useful for controlling decimal places, padding, and alignment.

Controlling Decimal Places

pi = 3.14159265
print(f"Pi to 2 decimal places: {pi:.2f}")
# Output: Pi to 2 decimal places: 3.14

Padding and Alignment

items = [("Apples", 1.50), ("Bananas", 0.75), ("Cherries", 3.20)]

for item, price in items:
    print(f"{item:<10} ${price:.2f}")

# Output:
# Apples     $1.50
# Bananas    $0.75
# Cherries   $3.20

The <10 specifier left-aligns the text and pads it to 10 characters wide. You can also right-align with > or center with ^. For example, {item:^10} centers the text within 10 characters. This is great for building tidy output in scripts and tools.

Adding Thousands Separators

population = 1482000
print(f"Population: {population:,}")
# Output: Population: 1,482,000

Debugging with f-Strings (Python 3.8+)

Python 3.8 added a handy shortcut: adding = after a variable name inside the braces prints both the variable name and its value. This is useful for quick debugging without writing separate print labels:

x = 42
print(f"{x=}")
# Output: x=42

A Few Things to Watch Out For

  • Quotes inside f-Strings: If your f-String uses double quotes, use single quotes inside the braces (or vice versa) to avoid conflicts.
  • Backslashes: You cannot use backslash escape sequences directly inside the curly braces in Python versions before 3.12. If you need a value that requires a backslash, assign it to a variable first and reference that variable inside the braces.
  • Python version: f-Strings require Python 3.6 or later. If you are working in a legacy Python 2 environment, they are not available.

What's Next

Now that you can format strings cleanly, the next logical step is understanding how Python handles collections of data. In the next post, we will cover Python lists: how to create them, access items, and use common list methods to manipulate data. Lists are one of the most used data structures in Python, and getting comfortable with them opens the door to loops, functions, and much more.