String Processing
String Formatting
Building dynamic output strings is essential for user messages, reports, and data display. Python provides multiple formatting approaches: legacy %-formatting, the str.format() method, and modern f-strings. Understanding all three helps you read existing code and choose the best tool for each situation.
Old-style formatting (%)
The original C-style formatting using the % operator.
# Old-style % formatting
name = "Alice"
age = 30
height = 5.8
# Basic formatting
print("Name: %s" % name)
print("Age: %d" % age)
print("Height: %.1f" % height)
# Multiple values (tuple)
print("Name: %s, Age: %d" % (name, age))
# Format specifiers
print("Integer: %d" % 42)
print("Float: %f" % 3.14159)
print("Scientific: %e" % 1000000)
print("Percentage: %.2f%%" % 95.5)
# Width and precision
print("Padded: %10s" % "test")
print("Number: %05d" % 42)
print("Decimal: %8.2f" % 3.14159)
Use %s for strings, %d for integers, %f for floats. Pass values as tuple.
str.format() method
Flexible formatting with positional and named placeholders.
# str.format() method
name = "Bob"
age = 25
balance = 1234.56
# Positional arguments
print("Name: {}, Age: {}".format(name, age))
# Indexed arguments
print("Age: {1}, Name: {0}".format(name, age))
# Named arguments
print("Name: {n}, Age: {a}".format(n=name, a=age))
# Mixed
print("{0} is {1} years old. {0} has ${2:.2f}".format(name, age, balance))
# From dictionary
data = {'name': 'Charlie', 'age': 35}
print("Name: {name}, Age: {age}".format(**data))
# Attribute access
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("David", 40)
print("Name: {p.name}, Age: {p.age}".format(p=person))
Use {} placeholders with .format(). Supports indexing and named arguments.
F-strings (modern)
Inline expressions directly in string literals using f-prefix.
# F-strings (formatted string literals)
name = "Eve"
age = 28
balance = 5432.10
# Basic f-string
print(f"Name: {name}, Age: {age}")
# Expressions inside f-strings
print(f"Next year {name} will be {age + 1}")
print(f"Double balance: ${balance * 2:.2f}")
# Method calls
text = "hello world"
print(f"Uppercase: {text.upper()}")
print(f"Title case: {text.title()}")
# Calculations
x, y = 10, 20
print(f"{x} + {y} = {x + y}")
print(f"{x} * {y} = {x * y}")
# Multiple lines
message = (
f"User Profile:\n"
f" Name: {name}\n"
f" Age: {age}\n"
f" Balance: ${balance:.2f}"
)
print(message)
Prefix string with f, embed expressions in {braces}. Most readable approach.
Number formatting
Format specifiers for decimal places, separators, and number bases.
# Number formatting with f-strings
pi = 3.14159265359
num =
# Decimal places
print(f"Pi: {pi:.2f}") # 2 decimals
print(f"Pi: {pi:.4f}") # 4 decimals
# Width and alignment
print(f"Pi: {pi:10.2f}") # Width 10, 2 decimals
print(f"Pi: {pi:012.2f}") # Zero-padded
# Thousands separator
print(f"Number: {num:,}")
print(f"Number: {num:_}") # Underscore separator
# Percentage
ratio = 0.756
print(f"Ratio: {ratio:.1%}") # 75.6%
print(f"Ratio: {ratio:.2%}") # 75.60%
# Scientific notation
big_num = 1234567890
print(f"Scientific: {big_num:e}")
print(f"Scientific: {big_num:.2e}")
# Binary, octal, hex
value = 42
print(f"Binary: {value:b}")
print(f"Octal: {value:o}")
print(f"Hex: {value:x}")
print(f"Hex (uppercase): {value:X}")
# Number formatting with f-strings
pi = 3.14159265359
num =
# Decimal places
print(f"Pi: {pi:.2f}") # 2 decimals
print(f"Pi: {pi:.4f}") # 4 decimals
# Width and alignment
print(f"Pi: {pi:10.2f}") # Width 10, 2 decimals
print(f"Pi: {pi:012.2f}") # Zero-padded
# Thousands separator
print(f"Number: {num:,}")
print(f"Number: {num:_}") # Underscore separator
# Percentage
ratio = 0.756
print(f"Ratio: {ratio:.1%}") # 75.6%
print(f"Ratio: {ratio:.2%}") # 75.60%
# Scientific notation
big_num = 1234567890
print(f"Scientific: {big_num:e}")
print(f"Scientific: {big_num:.2e}")
# Binary, octal, hex
value = 42
print(f"Binary: {value:b}")
print(f"Octal: {value:o}")
print(f"Hex: {value:x}")
print(f"Hex (uppercase): {value:X}")
# Number formatting with f-strings
pi = 3.14159265359
num =
# Decimal places
print(f"Pi: {pi:.2f}") # 2 decimals
print(f"Pi: {pi:.4f}") # 4 decimals
# Width and alignment
print(f"Pi: {pi:10.2f}") # Width 10, 2 decimals
print(f"Pi: {pi:012.2f}") # Zero-padded
# Thousands separator
print(f"Number: {num:,}")
print(f"Number: {num:_}") # Underscore separator
# Percentage
ratio = 0.756
print(f"Ratio: {ratio:.1%}") # 75.6%
print(f"Ratio: {ratio:.2%}") # 75.60%
# Scientific notation
big_num = 1234567890
print(f"Scientific: {big_num:e}")
print(f"Scientific: {big_num:.2e}")
# Binary, octal, hex
value = 42
print(f"Binary: {value:b}")
print(f"Octal: {value:o}")
print(f"Hex: {value:x}")
print(f"Hex (uppercase): {value:X}")
Use :.2f for decimals, :, for thousands, :b/:x/:o for binary/hex/octal.
Alignment and padding
Control width, alignment, and fill characters for formatted output.
# String alignment and padding
text = "Python"
num = 42
# Left align (default for strings)
print(f"'{text:<15}'")
# Right align (default for numbers)
print(f"'{text:>15}'")
# Center align
print(f"'{text:^15}'")
# Custom fill character
print(f"'{text:*<15}'")
print(f"'{text:->15}'")
print(f"'{text:=^15}'")
# Number alignment
print(f"'{num:<10}'")
print(f"'{num:>10}'")
print(f"'{num:^10}'")
# Table formatting
print("\nTable Example:")
print(f"{'Name':<12} {'Age':>5} {'Balance':>10}")
print(f"{'-'*12} {'-'*5} {'-'*10}")
print(f"{'Alice':<12} {30:>5} {1234.56:>10.2f}")
print(f"{'Bob':<12} {25:>5} {987.65:>10.2f}")
print(f"{'Charlie':<12} {35:>5} {5432.10:>10.2f}")
Use < left, > right, ^ center. Add fill character before alignment.
Practical example
Combine formatting techniques to build formatted reports.
# Practical example: Report generation
from datetime import datetime
class Transaction:
def __init__(self, date, description, amount):
self.date = date
self.description = description
self.amount = amount
# Sample data
transactions = [
Transaction(datetime(2026, 1, 15), "Grocery Store", -45.67),
Transaction(datetime(2026, 1, 18), "Salary Deposit", 2500.00),
Transaction(datetime(2026, 1, 20), "Electric Bill", -87.50),
Transaction(datetime(2026, 1, 22), "Restaurant", -32.40),
Transaction(datetime(2026, 1, 25), "Online Purchase", -156.89),
]
# Generate report
print("=" * 70)
print(f"{'BANK STATEMENT':^70}")
print("=" * 70)
print()
print(f"{'Date':<12} {'Description':<25} {'Amount':>15}")
print("-" * 70)
balance = 1000.00
for txn in transactions:
balance += txn.amount
date_str = txn.date.strftime("%Y-%m-%d")
# Color-code positive/negative (using symbols)
sign = "+" if txn.amount >= 0 else "-"
amount_str = f"{sign}${abs(txn.amount):.2f}"
print(f"{date_str:<12} {txn.description:<25} {amount_str:>15}")
print("-" * 70)
print(f"{'FINAL BALANCE:':<37} ${balance:>15,.2f}")
print("=" * 70)
# Summary statistics
total_deposits = sum(t.amount for t in transactions if t.amount > 0)
total_withdrawals = sum(t.amount for t in transactions if t.amount < 0)
print()
print("SUMMARY")
print(f" Total Deposits: ${total_deposits:>10,.2f}")
print(f" Total Withdrawals: ${abs(total_withdrawals):>10,.2f}")
print(f" Net Change: ${total_deposits + total_withdrawals:>10,.2f}")
Exercise: practical.py
Create a formatted receipt with aligned columns, currency formatting, and totals