String Formatting Methods

Difficulty: Beginner

Question

What are the different string formatting methods in Python? When should you use each?

Answer

Python has four main string formatting approaches:

1. % operator (old style): printf-style, still used in logging 2. str.format(): more powerful but verbose 3. f-strings (Python 3.6+): fastest, most readable, preferred for most use cases 4. Template strings: for user-provided templates (safe from injection)

f-strings (formatted string literals): - Evaluated at runtime - Can contain any Python expression - Support format spec: {value:.2f}, {text:>20}, {num:,} - Python 3.12+: f-strings allow any expression including nested quotes

Code examples

All Formatting Methods

name = 'Alice'
age = 30
price = 12345.678

# % operator (old style)
print('Hello, %s! You are %d years old.' % (name, age))

# str.format()
print('Hello, {}! You are {} years old.'.format(name, age))
print('Hello, {name}! You are {age}.'.format(name=name, age=age))

# f-strings (Python 3.6+) - preferred
print(f'Hello, {name}! You are {age} years old.')
print(f'Next year you will be {age + 1}.')  # Expressions!

# Format specification
print(f'{price:.2f}')     # 12345.68 (2 decimal places)
print(f'{price:,.2f}')    # 12,345.68 (with commas)
print(f'{price:e}')       # 1.234568e+04 (scientific)
print(f'{name:>20}')      # Right-align, width 20
print(f'{name:^20}')      # Center, width 20
print(f'{name:<20}|')     # Left-align, width 20
print(f'{42:08b}')        # 00101010 (8-bit binary)
print(f'{42:#x}')         # 0x2a (hex)

# Debugging with = (Python 3.8+)
value = 42
print(f'{value=}')        # value=42

Format specifications control number formatting (precision, commas, scientific), alignment (< > ^), fill character, and number base.

Template Strings and Advanced f-strings

from string import Template

# Template: safe for user-provided templates (no code execution)
t = Template('Hello, $name! You have $count messages.')
print(t.substitute(name='Bob', count=5))
print(t.safe_substitute(name='Charlie'))  # Missing keys → original placeholder

# f-string expressions
data = [1, 2, 3, 4, 5]
print(f'Sum: {sum(data)}, Mean: {sum(data)/len(data):.2f}')

import datetime
now = datetime.datetime.now()
print(f'Date: {now:%Y-%m-%d %H:%M}')

# Multi-line f-strings
report = (
    f'Name: {name}\n'
    f'Age: {age}\n'
    f'Price: ${price:,.2f}'
)
print(report)

# Python 3.12: nested f-strings
columns = ['name', 'age', 'email']
print(f"SELECT {', '.join(columns)} FROM users")

# Performance comparison (f-strings are fastest)
import timeit
print(timeit.timeit(f'f"Hello {name}"', globals=globals(), number=100000))
print(timeit.timeit('"Hello {}".format(name)', globals=globals(), number=100000))

Template.safe_substitute is safer than Template.substitute - missing keys leave the placeholder instead of raising KeyError. f-strings are 30% faster than format().

Key points

Concepts covered

f-strings, format(), % formatting, Template, format_spec